secretkeylabs / sats-connect Goto Github PK
View Code? Open in Web Editor NEWSats connect is a simple javascript library that connects apps to Bitcoin wallets
Home Page: https://www.npmjs.com/package/sats-connect
Sats connect is a simple javascript library that connects apps to Bitcoin wallets
Home Page: https://www.npmjs.com/package/sats-connect
Hello,
I see in the X-verse wallet it can render all NFTs. I want to do the same in my app, I need to find all the inscriptions in the wallet with their collection names to do further processing. Can I do this using sats-connect?
Thanks!
Hi,
I'm trying to sign a PSBT using the example code:
onSignTransactionClick = async () => {
const signPsbtOptions = {
payload: {
network: {
type: "Mainnet",
},
message: "Sign Transaction",
psbtBase64: "....",
broadcast: false,
inputsToSign: [
{
address: this.state.ordinalsAddress,
signingIndexes: [0],
sighash: 131
},
],
},
onFinish: (response) => {
alert(response.psbtBase64);
},
onCancel: () => alert("Canceled"),
};
await signTransaction(signPsbtOptions);
};
I need to sign the first and only input. The xverse dialog looks fine:
but when I confirm I get the error: "Error signing PSBT Error: Input with not allowed sigHash=131. Allowed: 0"
what can be the reason of this error? this.state.ordinalsAddress is the correct address. I also tried to sign an other psbtBase64 from an other site (using my wallet). So the psbt looks fine.
Given that a number of other wallets in the space are using the sats-connect standard, is there a best practice or any documentation around getting wallet providers and allowing the user to choose which they'd like to use?
I've seen some folks in discord talk about ME wallet taking precedence over xverse, and I have also seen the sample ME wallet implementations, but nothing seems standardised. Any guidance appreciated!
I am developing a runes platform and I have a specific functionality in mind regarding the distribution of funds during the minting process.
Is there a way to automatically send 1% of the minting fees (or any specified amount) to a particular wallet each time a new item is minted? This feature would be crucial for automatically distributing royalties or similar payments.
The goal is to ensure that every time an item is minted on our platform, a predetermined percentage of the transaction (in this case, 1%) is sent to a designated wallet address.
This feature is intended to streamline the process of royalties or fee distribution, making it more efficient and less prone to errors. Your advice on how to best achieve this would be greatly appreciated.
Thank you for your support and guidance!
Issue/Question:
Hello Sats Connect Team,
I'm currently integrating Sats Connect into my application to connect with Xverse wallets. First off, I want to express my appreciation for your work on this library—it's been instrumental in simplifying the interaction between our app and Bitcoin wallets.
As I'm delving deeper into the development process, I've identified a few potential enhancements that could significantly benefit the user experience and overall functionality of the library:
Listeners for Account and Network Changes: Is there a possibility to implement listeners that can detect and respond to changes in the user's account or the network? This feature would be incredibly useful for dynamically updating the application state in response to such changes.
Non-Intrusive Account Retrieval: Currently, retrieving a user's account involves a wallet pop-up where the user needs to confirm the action. While this is secure, it can sometimes be intrusive, especially for users who frequently interact with the application. Is there a way to streamline this process? Specifically, I'm interested in an option to get the account details without prompting the user with a wallet pop-up each time, assuming they've already granted permission.
These enhancements, if feasible, could greatly improve the user experience by providing more seamless interactions and reducing repetitive confirmation steps.
I understand that these features might require careful consideration, especially concerning security and privacy. I'm eager to hear your thoughts on whether these enhancements align with the vision and roadmap for Sats Connect.
Additionally, I'd like to highlight that this request is related to the implementation discussed in Issue #703 on the Xverse Web Extension repository. The successful integration of these features there would play a significant role in the effectiveness of the enhancements proposed here.
Thank you for your time and consideration. Looking forward to your insights.
Best regards.
It would be helpful to mention in your documentation that Minting with sat connect is not free and incurs fees, so that everyone is aware.
No response
I am unable to submit this tx
I am spending an input that has
OP_IF
${script.number.encode(lockTime).toString("hex")}
OP_CHECKLOCKTIMEVERIFY
OP_DROP
OP_ELSE
${alice}
OP_CHECKSIGVERIFY
OP_ENDIF
${bob}
OP_CHECKSIG
As script
I keep getting: non-mandatory-script-verify-flag (Locktime requirement not satisfied)
even if the locktime has past
0200000000010294b306e9deba3ff7b83a3e451612823e10a861efc2e9cc40862e5525ed99c9c70000000000feffffff8ad216085a471cc0a13994d0857a0f54640b7a439ea72742f3af951103d6b401000000001716001483b3b0bf2864338e157d6afa74c9382e2f155ae6ffffffff032202000000000000225120f790a969c43abc0ecd34ccc1a2244c7feed623b70583930824b581fae6885ee7e80300000000000022002074f64a2e547a8e226ef0ed0e4a9856eb4a6566e2ddf52daa8822c1dcb0adc10b0000000000000000236a217b226964223a22363630323837656136366563653264613665356533376633227d0347304402206577f3749d0cc3fdb655494c138aa7166cf79de56fb02f9cba5e773eb7fbf0e402202b1f4c0c9b74eb20163dd1feebf17e0aba4f1af3a5358ea2af28ce9d23976de78101015063040a880266b1756721035a99c71780945305f3a20356d55bcc7e8b681c3ef84c537cee5ee7e7da23163ead68210307bf5747e92385958eafaa1da8d6649adc452b9f69fb3cf1fac6407a73a149d7ac02483045022100df61fd5bbeca42dc9f9835d472d732ddf563aebdec8382bce79761e7b256bcb502206bb38de746310de674e18d2d5131c6dadef3cc86d6e02d94b4bb9ede89811e9181210307bf5747e92385958eafaa1da8d6649adc452b9f69fb3cf1fac6407a73a149d700000000
Hi I am trying to sign this psbt.
Raw base64 PSBT:
cHNidP8BAP1DAQIAAAAEC4oh5Bfz1UCdX8+RvDBodB5E/k3i8ae5Q7OHB0BsZFcAAAAAAP////8q0Vfy7QeKe612DANmR9NLOyZEYCpgQXOI864savGaVAAAAAAA//////eU9Mca42tI2RbL9LSePT95BBQHw7zSn83gPggS+DHjAAAAAAD9////KtFX8u0HinutdgwDZkfTSzsmRGAqYEFziPOuLGrxmlQDAAAAAP////8EoA8AAAAAAAAWABRG+puN8Rdm5ZniJvdzwp3/x9vNkhAnAAAAAAAAIlEghXRfbNOxsdp/3PoO+9kA1Bx2zgQMle4OAuL9jtf+76sQJwAAAAAAACJRINXhm8upw0QrrpC+6g3uLldgF37nrF1BlhGOZXu7MCFBBH4AAAAAAAAXqRSOFV167CO6HneNXI8b1TuBweJV9YcAAAAAAAEBH9AHAAAAAAAAFgAUpO6TPSrWG/GaJmF7Q5qaArJXrdQBAwQBAAAAAAEBH9AHAAAAAAAAFgAUVqiGgXC/LtZcdD1dcA1FiEhJTeEBAwQBAAAAAAEAsgIAAAACbG47gFYsNEQcqiDH11xz+B7Au07SN9rVZwiL4AP0xj8AAAAAAP3///8PCnnkz+O+Ly3Fb7GypSpVBBSLJeZFjrTKMWHFAus5FAEAAAAA/////wIQJwAAAAAAACJRINXhm8upw0QrrpC+6g3uLldgF37nrF1BlhGOZXu7MCFBqBYfAgAAAAAiUSCMa++bywFYHxziQdX4iNdm8QSMpT1yGRCIATs/X3GWUwAAAAABASsQJwAAAAAAACJRINXhm8upw0QrrpC+6g3uLldgF37nrF1BlhGOZXu7MCFBAQMEgwAAAAEIQwFBnBPixDdU9/0ybWM56CEQmgtzAwHcVw8E0hDLm9dB55XxLYO3OrxE1QYOYWvCi1Nt//+58f06XPh9QTezMIkMuoMAAQD9WgECAAAABKmjk2jSqQSdFQmlO3ENB+1rpA4m5fAeIcjMLX6KP8glAQAAAAD/////qaOTaNKpBJ0VCaU7cQ0H7WukDibl8B4hyMwtfoo/yCUAAAAAAP////86J+7W4aeuyrF3FftUGxDcJKd4cJWsmAYHp37JsnsAAAAAAAAA/f///9NAMgY0jKE7C6o3gAP0aVaeeZaVzCoWu1m+K+53K14QAQAAABcWABSocg1wHbw3K0prtPAJ26thGWTTa/////8E0AcAAAAAAAAWABRWqIaBcL8u1lx0PV1wDUWISElN4RAnAAAAAAAAIlEghXRfbNOxsdp/3PoO+9kA1Bx2zgQMle4OAuL9jtf+76sQJwAAAAAAACJRIJT2U14DpfCaVeihkdwRhKr66qzIfaSOAm2ka+Ulb+VsbOUAAAAAAAAXqRSOFV167CO6HneNXI8b1TuBweJV9YcAAAAAAQQWABSocg1wHbw3K0prtPAJ26thGWTTawAAAAAA
My signing function
signByXverse: async (psbt, address) => {
let psbtBase64 = '';
const signPsbtOptions = {
payload: {
network: {
type: 'Mainnet',
} as BitcoinNetwork,
message: 'Sign Transaction',
psbtBase64: psbt,
broadcast: false,
inputsToSign: [
{
address, // paymentAddress
signingIndexes: [3],
sigHash: bitcoin.Transaction.SIGHASH_ALL,
},
],
},
onFinish: ({ psbtBase64: _psbtBase64, txId: _txId }) => {
psbtBase64 = _psbtBase64;
},
onCancel: () => alert('Request canceled.'),
};
await signTransaction(signPsbtOptions);
debugger;
const finalPsbt = bitcoin.Psbt.fromBase64(psbtBase64, {
network: NETWORK,
}).finalizeInput(3);
return finalPsbt;
},
I am encountering an issue where a rune etching transaction was successfully submitted and confirmed on the blockchain, but the etched runes are not visible on any rune explorers. I used the runes_etch
API method from the Sats Connect library.
{
"destinationAddress": "tb1qzjhm26d90dga8dp3tgx07n76aky7psz4clagaz",
"feeRate": 2,
"runeName": "CCCCXCXCSXCZ",
"divisibility": 8,
"symbol": "C",
"premine": "1000",
"isMintable": true,
"terms": {
"amount": "1000",
"cap": "1000"
}
}
The rune etching should be visible on the rune explorers such as Bitrune and RuneBTC after the transaction is confirmed on the blockchain.
The transaction was confirmed as seen in the transaction on Mempool:
67e6cc2a7e4beaec8afccf28aba579b81a377550c5bdff635c04799087614e05
However, the runes are not listed in the following rune explorers:
Importing sats-connect
when using NextJS throws window is undefined due to server side rendering.
I suggest checking for typeof window !== "undefined"
when using the window object to enable SSG and SSR compatibility. @sats-connect/core
mainly works, but a few functions like getProviders
fail if called outside useEffects.
I am following the tutorial at link
And I am at the point where using a script like this:
const locking_script = script.compile([
opcodes.OP_DUP,
opcodes.OP_HASH160,
crypto.hash160("028f5ced5649da371758f280635f94a558c68eee2ac4c7f07034425e97c60352bd"),
opcodes.OP_EQUALVERIFY,
opcodes.OP_CHECKSIG
])
I got the address bc1qq3r80lygdgl3wmpa5rt9l57xfepr9hkf7728q090z75k38magfvqzdadt7
However in order to redeem I need to pass the sig in the witness therefore my first try was to sign the psbts that I get:
cHNidP8BAFMCAAAAAcZjU/fLSzKbXfUah9mtfhp6DDjrK3mcY6Ea9I9il9/JAAAAAAD/////AWhCAAAAAAAAF6kUFMjwOBiDWXNvb7+ZpflEjRmAg0aHAAAAAAABASsgTgAAAAAAACIAIARGd/yIaj8XbD2g1l/Txk5CMt7J95RwPK8XqWiffUJYAQUZdqkUGzRXtbBbTTEngIq2QOEl/N8T6NeIrAAA
however this error pops up and I can't proceed, probably I am missing something
Is there any API for sending inscription?
Equivalent of this from Unisat wallet: https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet#sendinscription
2.3.0
in ./node_modules/@sats-connect/ui/dist/index.js
Module parse failed: Unexpected token (1202:29)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
const a = Kr(o);
if (!a && t) {
-> const l = new Error(i ?? Si(n, r));
throw l.name = "ContextError", (f = Error.captureStackTrace) == null || f.call(Error, l, s), l;
}
No response
No response
No response
No response
I tried to find getbalance on Xverse wallet, and unable to get the API yet.
Is there any documentation or demo available?
When signing a message i get a signature that is 65 byte long what is up with that and what is the format of the public key, im having trouble verfiying the signature with bitcoinjs-lib because it doesn't accept the signature.
We are currently developing a feature that involves a runes-locking mechanism using your APIs. However, we noticed that there isn't a method for implementing time locks on UTXOs either when they're created or transferred.
Our goal is to add time locks to UTXOs to control their usability based on predefined conditions. The intended approach is to intercept received transactions and apply a time-lock script to the specific UTXOs we wish to lock.
Looking forward to your guidance and any resources you can provide!
Hi,
Just wanted to ask if there's a plan to support signing multiple PSBTs that can be used with Xverse wallet. Or is it already possible at the moment? Thanks!
Hi,
Is it possible to construct a transaction to mint a Rune?
Hey guys, so this is probably not related to sats-connect but since I am facing it with XVerse maybe you can help me:
Here a raw signed TX that is not able to submit, the error is:
sendrawtransaction RPC error: {"code":-26,"message":"scriptpubkey"}
This transaction on testnet doesnt' have any issues, is it related to OP_RETURN? does it have some restrictions on mainnet?
0200000000010d2c17447f911aad6344769ad8ea55411ec1c794050c86f0d5af540ff1d126c89c01000000171600140f2a9ea5758f3bc666c5a0fe23cad3b7e6c95610ffffffff100edf08da69cbfdad376f5deab1910cfab88c24cf76613a3df1ec2b7a77066105000000171600140f2a9ea5758f3bc666c5a0fe23cad3b7e6c95610ffffffff100edf08da69cbfdad376f5deab1910cfab88c24cf76613a3df1ec2b7a77066104000000171600140f2a9ea5758f3bc666c5a0fe23cad3b7e6c95610ffffffff100edf08da69cbfdad376f5deab1910cfab88c24cf76613a3df1ec2b7a77066100000000171600140f2a9ea5758f3bc666c5a0fe23cad3b7e6c95610ffffffff5f409de07b795b3827e881cc7f903cc36b889e678de419a79851e6cb833e3b1e05000000171600140f2a9ea5758f3bc666c5a0fe23cad3b7e6c95610ffffffff5f409de07b795b3827e881cc7f903cc36b889e678de419a79851e6cb833e3b1e04000000171600140f2a9ea5758f3bc666c5a0fe23cad3b7e6c95610ffffffff5f409de07b795b3827e881cc7f903cc36b889e678de419a79851e6cb833e3b1e00000000171600140f2a9ea5758f3bc666c5a0fe23cad3b7e6c95610ffffffff3582f7c38121f034af09379db6a3572fa4ca51f09a8bf5efe038bf0b5a1f4e3c07000000171600140f2a9ea5758f3bc666c5a0fe23cad3b7e6c95610ffffffff3582f7c38121f034af09379db6a3572fa4ca51f09a8bf5efe038bf0b5a1f4e3c06000000171600140f2a9ea5758f3bc666c5a0fe23cad3b7e6c95610ffffffff3582f7c38121f034af09379db6a3572fa4ca51f09a8bf5efe038bf0b5a1f4e3c05000000171600140f2a9ea5758f3bc666c5a0fe23cad3b7e6c95610ffffffff3582f7c38121f034af09379db6a3572fa4ca51f09a8bf5efe038bf0b5a1f4e3c04000000171600140f2a9ea5758f3bc666c5a0fe23cad3b7e6c95610ffffffff3582f7c38121f034af09379db6a3572fa4ca51f09a8bf5efe038bf0b5a1f4e3c03000000171600140f2a9ea5758f3bc666c5a0fe23cad3b7e6c95610ffffffff3582f7c38121f034af09379db6a3572fa4ca51f09a8bf5efe038bf0b5a1f4e3c02000000171600140f2a9ea5758f3bc666c5a0fe23cad3b7e6c95610ffffffff04e803000000000000220020fd486ac739689ff8773628736fbc9ecfb77cf4edc982cbb952b13771a1d3742a6630b800000000002200207f4bce1d98b18e5592185a1e4a0664fec4584d68736271651200997f99113bf9f61847020000000017a91414c8f038188359736f6fbf99a5f9448d198083468700000000000000009d6a4c9a7b22636f6c6c223a22626974636f696e2d70757070657473222c2270416d6e74223a31323037313031342c226c416d6e74223a323839373034332c22617072223a3132352c22704b6579223a22303238663563656435363439646133373137353866323830363335663934613535386336386565653261633463376630373033343432356539376336303335326264222c2264617973223a377d024730440220718de1ab516958f22b5607795a3f4ea18aa18a93958638b3a8167203521e6309022027eef3e64506bdaf7218920f99ee3e4264bec5d56476e927cc722d902295300e0121028f5ced5649da371758f280635f94a558c68eee2ac4c7f07034425e97c60352bd02473044022015e926ebd9d1ad089750a0419e519bbe5e175659b789fccc749d99e91bd97575022009f66e7f1b2218121395e26984b3dd543a6ad59f82022372128bee40517e67920121028f5ced5649da371758f280635f94a558c68eee2ac4c7f07034425e97c60352bd024730440220363f3a52d0df8b932d243990d11ae9bd5ee88f4ee462ca3e3fe05a8d0e94bf5b022028d14468de98f4cdd682b09b006def497236dc452f66c9db0b174c5e5708705f0121028f5ced5649da371758f280635f94a558c68eee2ac4c7f07034425e97c60352bd0247304402200c8dc8243131f27f686257bffaf02083f347115f011ab142c50d8a764dba29b3022025f33170cde3028b637f2133d9c5f3dc20cd19efcf48882cb429be88f7165a050121028f5ced5649da371758f280635f94a558c68eee2ac4c7f07034425e97c60352bd0247304402205d2b5e650d80499efa0ba3f99e650e36250e742e7005e5aba9fccf0a0fa8e599022010b9cdd848f44e020f21786124ec819e7cd3945184737de1b1b8b544ded48e120121028f5ced5649da371758f280635f94a558c68eee2ac4c7f07034425e97c60352bd024730440220104e62f2b11c316e42b02ae87cccf47bfb32f28ae137282874bc32571528c34c0220542e2be186ca53fb1ceea8168eb8d1a319a6ff269c92c1a3001123795ce8a5ac0121028f5ced5649da371758f280635f94a558c68eee2ac4c7f07034425e97c60352bd02483045022100e9e6998f6a864b82c3976bb48894a564af3345ad5fa518246cfc42867db884f50220186dad88e858b92f1cb9c074d73b54a6d7979d7596ba7ad13c20ae2f3c5614dc0121028f5ced5649da371758f280635f94a558c68eee2ac4c7f07034425e97c60352bd0247304402205777caec1d7b213c12ca2bfaea8507a316c0d9d9329b164280c6b06a4565ac52022043bdca34157e731f554370d3d78fcd401ef509d7dfba0480ac08915fd44aad700121028f5ced5649da371758f280635f94a558c68eee2ac4c7f07034425e97c60352bd0247304402200f8c4fb9ac3b57ac4386e958bd18df39f62eb48ba1e435aa095aabf834a2a09802204441acffafd3f0616dc98ea4f27c063f20a9b0f644e587a984db21
Hi to everyone I would like to ask how can I get the hash of the message I am signing starting from the message I put inside the function, since it seems is not exactly the hash of the message itself
Is there any algo or encoding applied?
Thanks
No response
I can create a listing psbt (sell order).
But I got:
Failed to sign transaction
Error signing PSBT Error: No taproot scripts signed
Inputs:
[
{
"nonWitnessUtxo": {
"type": "Buffer",
"data": [
...
]
},
"witnessUtxo": {
"script": {
"type": "Buffer",
"data": [
...
]
},
"value": 1897
},
"sighashType": 131
}
]
signPsbtListingXverse: async ({ psbt, address }) => {
let psbtBase64 = '';
const signPsbtOptions = {
payload: {
network: {
type: NETWORK_NAME,
} as BitcoinNetwork,
message: 'Sign Transaction',
psbtBase64: psbt.toBase64(),
broadcast: false,
inputsToSign: [
{
address, // ordinal address
signingIndexes: [0],
sigHash: 131,
},
],
},
onFinish: ({ psbtBase64: _psbtBase64, txId: _txId }) => {
psbtBase64 = _psbtBase64;
},
onCancel: () => alert('Request canceled.'),
};
await signTransaction(signPsbtOptions);
const finalPsbt = bitcoin.Psbt.fromBase64(psbtBase64, {
network: NETWORK,
}).finalizeInput(0);
return finalPsbt;
},
This is how I retrieve the account's public key from Xverse:
const getAddressOptions = {
payload: {
purposes: ['ordinals'],
message: 'Address for receiving Ordinals',
network: {
type:'Testnet'
},
},
onFinish: (response) => {
walletAddress = response.addresses[0].address
walletPublicKey = response.addresses[0].publicKey
},
onCancel: () => alert('Request canceled'),
}
}
await getAddress(getAddressOptions);
The walletPublicKey
returned has the following format: 12f022914336dea00c12940dcae0481fbf87484f09f88f6d0ac1b552997faa25
.
This looks to me like a compressed public key format but without the 02/03
prefix indicating the position of the Y point on the curve. Is my assumption of the key format correct and if so, is there a way to have the prefix included?
Can we generate a request for bulk inscription creation using sata-connect @victorkirov @olistic @teebszet @m-aboelenein @yknl ?
[Connect] Error during send btc request TypeError: provider.sendBtcTransaction is not a function
const payload: SignPsbtParams = {
psbt: data.psbt,
allowedSignHash: btc.SigHash.SINGLE | btc.SigHash.DEFAULT_ANYONECANPAY,
signInputs: {
[rawFormData.sellerPaymentAddress]: [0],
[rawFormData.sellerOrdinalsAddress]: [1, 2],
},
broadcast: false,
};
const response = await request('signPsbt', payload);
Does anyone have any ideas?
Hey guys, I'm trying to use the getAddress method to get an Xverse wallet address on my Typescript + Next JS app and I am having trouble with constructing the purposes array in the option being passed to the getAddress method.
Currently, my options look like this;
const getAddressOptions = { payload: { purposes: ["ordinals", "payment"], message: "Address for interracting with MyDapp", network: { type: "Mainnet", }, }, onFinish: (response: any) => { const addresses = { ordinal: response.addresses[0].address, payment: response.addresses[1].address, }; setUserAddress(addresses.ordinal); }, onCancel: () => alert("Request canceled"), };
The TS compiler keeps saying this
"Argument of type '{ payload: { purposes: string[]; message: string; network: { type: string; }; }; onFinish: (response: any) => void; onCancel: () => void; }' is not assignable to parameter of type 'GetAddressOptions'.
The types of 'payload.purposes' are incompatible between these types.
Type 'string[]' is not assignable to type 'AddressPurposes[]'.
Type 'string' is not assignable to type 'AddressPurposes' "
Any help on how to use the appropriate type to configure the options?
Also, a Typecript-focused guide in the docs will be lovely. Thanks!
I got this error, the inputs comes from a multisig script therefore it will need 2 signatures to be valid.
I am using sigHash: 131 // SIGHASH_SINGLE | ANYONECANPAY as shown in your tutorial
What am I doing wrong? I would like the first signer to approve the first input to be spent if there is a second output fixed
How can I do it?
Transaction/sign: legacy input without nonWitnessUtxo, can result in attack that forces paying higher fees. Pass allowLegacyWitnessUtxo=true, if you sure
I just connected my address and got this as pubKey for ordinals
14803e27545dc1c220f5089a6ada4fa5c609dd50886d7abb47d30a866c981256
I tried to get the Address shown on the wallet with this:
const toXOnly = pubKey => (pubKey.length === 32 ? pubKey : pubKey.slice(1, 33));
let OrdinalPubKey =
"035a99c71780945305f3a20356d55bcc7e8b681c3ef84c537cee5ee7e7da23163e";
const BorrowerOrdinalPubKeyBuffer = Buffer.from(
OrdinalPubKey,
"hex"
);
// Create a P2WPKH (Pay to Witness Public Key Hash) script
const p2trBorrower = payments.p2tr({
pubkey: toXOnly(OrdinalPubKeyBuffer),
network: network,
});
console.log(p2trBorrower)
Even without toXOnly
I keep getting different address than what I see in the wallet
tb1p53y6uvzx4uzw6m2hht7m0p8xlu8kqlmrulm5ng2kxsmpkfwndpjq64gl55
What's wrong?
Hello, can you provide some example to inscribe an html with sign transaction?
In the Unisat wallet, we can listen for account and network changes using the following event listeners:
unisat.on('accountsChanged', handleAccountsChanged);
unisat.on('networkChanged', handleNetworkChanged);
This feature is crucial for maintaining the app's responsiveness to changes in the user's wallet settings, such as switching accounts or networks, which is common in blockchain applications.
I suggest adding support for event listeners in the Xverse wallet that can handle 'accountsChanged' and 'networkChanged' events. This would make the wallet more versatile and user-friendly, particularly for applications that need to react in real-time to changes in the user's wallet configuration.
Ideally, the implementation would allow developers to use event listeners similar to those in Unisat.
xverse.on('accountsChanged', handleAccountsChanged);
xverse.on('networkChanged', handleNetworkChanged);
Benefits:
I am signing a multisignature and as you see I am able to get the transacion ID and the finalized raw tx before I approve my signature, this means that signTransaction() function doesn't wait for me to sign and could potentially be exploited by someone who tries to make me sign a bad tx
I don't sign but anyway it was done and could be propagated by attacker
A bit more of details
import Wallet from '../sats-connect';
I include this in my app.js file but on the client, it gets an error that it doesn't find it
Please help
It would be super useful for the signMultipleTransactions
to have a broadcast flag, similar to signTransaction
so that one can easily sign and broadcast multiple psbts.
On that note, are there any documented steps of taking the signed psbt returned from either method (signTransaction
with broadcast false
or signMultipleTransactions
) and getting the hex that can be broadcast?
Currently onCancel is very opaque and doesnt return the error that caused the cancel
Is there any function from which I can listen the address change in xverse wallet?
Currently following this https://docs.xverse.app/sats-connect/guides/verify-message-signature
But there are no references about where to get
decodeBech32
secp256k1.recover
decodeSignature
and so on...
Let me know where can I import them from thanks
We've encountered an issue where Xverse does not support Schnorr signatures for signing messages, which are the default validation method for Nostr relays. This is causing problems when we try to produce a valid signature for a Nostr event.
Looking at the verifySignature method in nostr-tools, it seems that the issue lies in the inability to produce a valid signature that the Nostr event can accept.
Could you please provide some guidance on how we can proceed in this scenario? Any advice or potential workarounds would be greatly appreciated, if there's any, if I should go ahead and implement the code and open a PR for it
Thank you for your time and assistance.
I'm using the sats-connect library in my code which are mostly async javascript functions.
Now I want to await the response from sats-connect, instead of registering the onFinish callback functions.
Hi,
Creating a PSBT using outputs from a transaction with unknown output causes error;
Error signing PSBT Error: Transaction/output: unknown output script type, there is a chance that input is unspendable. Pass allowUnkownScript=true, if you sure
I can't see a way to pass { allowUnknowInput: true, allowUnknowOutput: true } to the wallet to get it to ignore the unknown input/outputs because
transaction.toPSBT()
scure btc signer does not preserve these options on the PSBT and SignTransactionOptions
has no options for ignoring unknown outputs?
Hello, how to use sats-connect to send btc,
There is no sendBtcTransaction method in the BitcoinProvider injected by Xverce wallet
I have created a funded P2WSH script, which is an HTLC. I now want to create a PSBT which will be signed by another wallet to withdraw the funds.
The problem is that the PSBT signing is throwing the following error: Input script doesn't have pubKey. I am not sure why, or how to add this pubkey to the PSBT correctly.
The following is a details breakdown of the steps I am taking to create, fund and (failing to) redeem the HTLC.
Address from xverse (ordinals): tb1pnz86gezf5dzmja9q86z5agnmgjj29f00nxjj9jx0fsss6kkyh03sjkqhpd
Public Key: 59fff87c1bb3f75d34ea9d1588b72d0df43540695671c7a5ad3ec6a71d44bd79
Script to create the HTLC:
import bitcoin from 'bitcoinjs-lib';
import crypto from 'crypto';
function createHTLC(secret, lockduration, recipientPubKey, senderPubKey, networkType) {
const network = networkType === 'testnet' ? bitcoin.networks.testnet : bitcoin.networks.bitcoin;
const secretHash = crypto.createHash('sha256').update(Buffer.from(secret, 'utf-8')).digest();
const recipientHash = bitcoin.crypto.hash160(Buffer.from(recipientPubKey, 'hex'));
const senderHash = bitcoin.crypto.hash160(Buffer.from(senderPubKey, 'hex'));
const redeemScript = bitcoin.script.compile([
bitcoin.opcodes.OP_IF,
bitcoin.opcodes.OP_SHA256,
secretHash,
bitcoin.opcodes.OP_EQUALVERIFY,
bitcoin.opcodes.OP_DUP,
bitcoin.opcodes.OP_HASH160,
recipientHash, // Hashed recipient public key
bitcoin.opcodes.OP_ELSE,
bitcoin.script.number.encode(lockduration),
bitcoin.opcodes.OP_CHECKLOCKTIMEVERIFY,
bitcoin.opcodes.OP_DROP,
bitcoin.opcodes.OP_DUP,
bitcoin.opcodes.OP_HASH160,
senderHash, // Hashed sender public key
bitcoin.opcodes.OP_ENDIF,
bitcoin.opcodes.OP_EQUALVERIFY,
bitcoin.opcodes.OP_CHECKSIG,
]);
// Calculate the P2WSH address and scriptPubKey
const redeemScriptHash = bitcoin.crypto.sha256(redeemScript);
const scriptPubKey = bitcoin.script.compile([
bitcoin.opcodes.OP_0, // Witness version 0
redeemScriptHash
]);
const p2wshAddress = bitcoin.payments.p2wsh({
redeem: { output: redeemScript, network },
network
}).address;
console.log('\nCreated an HTLC Script!');
console.log('-------------------------------------------------');
console.log('P2WSH Bitcoin Deposit Address for HTLC:', p2wshAddress);
console.log('Witness Script Hex:', redeemScript.toString('hex'));
console.log('Redeem Block Number:', lockduration);
console.log('Secret (for spending):', secret);
console.log('SHA256(Secret) (for HTLC creation):', secretHash.toString('hex'));
console.log('ScriptPubKey Hex:', scriptPubKey.toString('hex'));
console.log('-------------------------------------------------');
// To fund the HTLC, send BTC to the p2wsh.address
// Redeeming the HTLC would involve creating a transaction that spends from this address
// using the provided witnessScript, which would be included in the transaction's witness field
}
// Example usage
createHTLC(
'mysecret',
1, // locktime in blocks
"59fff87c1bb3f75d34ea9d1588b72d0df43540695671c7a5ad3ec6a71d44bd79",
"59fff87c1bb3f75d34ea9d1588b72d0df43540695671c7a5ad3ec6a71d44bd79",
'testnet'
);
This successfully creates the P2WSH transaction and gives the following output to the screen
Created an HTLC Script!
-------------------------------------------------
P2WSH Bitcoin Deposit Address for HTLC: tb1q5cyw034kcvsp6fsfx9skeq93vhvuqghmjc9y8xdhjll8m9thrn9q5mv0nr
Witness Script Hex: 63a820652c7dc687d98c9889304ed2e408c74b611e86a40caa51c4b43f1dd5913c5cd08876a914e399056c4ca63571aca44fc2d11b3fdac69a37e06751b17576a914e399056c4ca63571aca44fc2d11b3fdac69a37e06888ac
Redeem Block Number: 1
Secret (for spending): mysecret
SHA256(Secret) (for HTLC creation): 652c7dc687d98c9889304ed2e408c74b611e86a40caa51c4b43f1dd5913c5cd0
ScriptPubKey Hex: 0020a608e7c6b6c3201d260931616c80b165d9c022fb960a4399b797fe7d95771cca
-------------------------------------------------
Then I fund the script via xverse by sending bitcoin directly to
tb1q5cyw034kcvsp6fsfx9skeq93vhvuqghmjc9y8xdhjll8m9thrn9q5mv0nr
https://mempool.space/testnet/tx/be9cc0e300d1c01b7fdbeeff1c99acc0fb8a7d9e8d025547b7bfc9635dedcbb3
The ScriptPubKey on mempool.space seems to match mine
0020a608e7c6b6c3201d260931616c80b165d9c022fb960a4399b797fe7d95771cca
Then it's time to create the PSBT. I can't immediately see any issues with how I am creating this PSBT. Do I need to add the public key somewhere?:
import * as bitcoin from 'bitcoinjs-lib';
import crypto from 'crypto';
import * as tinysecp256k1 from 'tiny-secp256k1';
// Initialize ECC library
import * as bitcoinjs from "bitcoinjs-lib";
import * as ecc from "tiny-secp256k1";
bitcoin.initEccLib(ecc);
function createSpendPSBT(secret, lockduration, scriptPubKeyHex, htlcTxId, htlcOutputIndex, refundAmount, recipientPubKey, senderPubKey, recipientAddress, networkType) {
const network = networkType === 'testnet' ? bitcoin.networks.testnet : bitcoin.networks.bitcoin;
const secretHash = crypto.createHash('sha256').update(Buffer.from(secret, 'utf-8')).digest();
// Recreate the HTLC script using the provided secret
const recipientHash = bitcoin.crypto.hash160(Buffer.from(recipientPubKey, 'hex'));
const senderHash = bitcoin.crypto.hash160(Buffer.from(senderPubKey, 'hex'));
const redeemScript = bitcoin.script.compile([
bitcoin.opcodes.OP_IF,
bitcoin.opcodes.OP_SHA256,
secretHash,
bitcoin.opcodes.OP_EQUALVERIFY,
bitcoin.opcodes.OP_DUP,
bitcoin.opcodes.OP_HASH160,
recipientHash, // Hashed recipient public key
bitcoin.opcodes.OP_ELSE,
bitcoin.script.number.encode(lockduration),
bitcoin.opcodes.OP_CHECKLOCKTIMEVERIFY,
bitcoin.opcodes.OP_DROP,
bitcoin.opcodes.OP_DUP,
bitcoin.opcodes.OP_HASH160,
senderHash, // Hashed sender public key
bitcoin.opcodes.OP_ENDIF,
bitcoin.opcodes.OP_EQUALVERIFY,
bitcoin.opcodes.OP_CHECKSIG,
]);
const scriptPubKey = Buffer.from(scriptPubKeyHex, 'hex');
console.log("Creating PSBT");
// Create a PSBT
const psbt = new bitcoin.Psbt({ network: network })
.addInput({
hash: htlcTxId,
index: htlcOutputIndex,
sequence: 0xfffffffe, // Necessary for OP_CHECKLOCKTIMEVERIFY
witnessUtxo: {
script: scriptPubKey,
value: refundAmount,
},
witnessScript: redeemScript,
})
.addOutput({
address: recipientAddress,
value: refundAmount - 1000, // Subtract a nominal fee
})
.setVersion(2)
.setLocktime(lockduration);
console.log("PSBT to be signed:", psbt.toBase64());
}
// Example usage (Fill in the actual values)
createSpendPSBT(
"mysecret",
0,
"0020a608e7c6b6c3201d260931616c80b165d9c022fb960a4399b797fe7d95771cca",
"be9cc0e300d1c01b7fdbeeff1c99acc0fb8a7d9e8d025547b7bfc9635dedcbb3",
0,
1000,
"59fff87c1bb3f75d34ea9d1588b72d0df43540695671c7a5ad3ec6a71d44bd79",
"59fff87c1bb3f75d34ea9d1588b72d0df43540695671c7a5ad3ec6a71d44bd79",
"tb1pnz86gezf5dzmja9q86z5agnmgjj29f00nxjj9jx0fsss6kkyh03sjkqhpd",
"testnet",
);
//createSpendPSBT(secret, lockduration, scriptPubKey, htlcTxId, htlcOutputIndex, refundAmount, recipientPubKey, senderPubKey, recipientAddress, networkType)
This gives me the following PSBT:
cHNidP8BAF4CAAAAAbPL7V1jyb+3R1UCjZ59ivvArJkc/+7bfxvA0QDjwJy+AAAAAAD+////AQAAAAAAAAAAIlEgmI+kZEmjRbl0oD6FTqJ7RKSipe+ZpSLIz0whDVrEu+MAAAAAAAEBK+gDAAAAAAAAIgAgpgjnxrbDIB0mCTFhbICxZdnAIvuWCkOZt5f+fZV3HMoBBVljqCBlLH3Gh9mMmIkwTtLkCMdLYR6GpAyqUcS0Px3VkTxc0Ih2qRTjmQVsTKY1caykT8LRGz/axpo34GcAsXV2qRTjmQVsTKY1caykT8LRGz/axpo34GiIrAAA
When I decode it, so I can inspect the contents, I get the following
{
"tx": {
"txid": "a1eaefe490f5d3be11fbd6a5afeffcff20a9e92cfde3363484168c9f5769c57a",
"hash": "a1eaefe490f5d3be11fbd6a5afeffcff20a9e92cfde3363484168c9f5769c57a",
"version": 2,
"size": 94,
"vsize": 94,
"weight": 376,
"locktime": 0,
"vin": [
{
"txid": "be9cc0e300d1c01b7fdbeeff1c99acc0fb8a7d9e8d025547b7bfc9635dedcbb3",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967294
}
],
"vout": [
{
"value": 0.00000000,
"n": 0,
"scriptPubKey": {
"asm": "1 988fa46449a345b974a03e854ea27b44a4a2a5ef99a522c8cf4c210d5ac4bbe3",
"desc": "rawtr(988fa46449a345b974a03e854ea27b44a4a2a5ef99a522c8cf4c210d5ac4bbe3)#4xpnet5r",
"hex": "5120988fa46449a345b974a03e854ea27b44a4a2a5ef99a522c8cf4c210d5ac4bbe3",
"address": "tb1pnz86gezf5dzmja9q86z5agnmgjj29f00nxjj9jx0fsss6kkyh03sjkqhpd",
"type": "witness_v1_taproot"
}
}
]
},
"global_xpubs": [
],
"psbt_version": 0,
"proprietary": [
],
"unknown": {
},
"inputs": [
{
"witness_utxo": {
"amount": 0.00001000,
"scriptPubKey": {
"asm": "0 a608e7c6b6c3201d260931616c80b165d9c022fb960a4399b797fe7d95771cca",
"desc": "addr(tb1q5cyw034kcvsp6fsfx9skeq93vhvuqghmjc9y8xdhjll8m9thrn9q5mv0nr)#wjcfmgw8",
"hex": "0020a608e7c6b6c3201d260931616c80b165d9c022fb960a4399b797fe7d95771cca",
"address": "tb1q5cyw034kcvsp6fsfx9skeq93vhvuqghmjc9y8xdhjll8m9thrn9q5mv0nr",
"type": "witness_v0_scripthash"
}
},
"witness_script": {
"asm": "OP_IF OP_SHA256 652c7dc687d98c9889304ed2e408c74b611e86a40caa51c4b43f1dd5913c5cd0 OP_EQUALVERIFY OP_DUP OP_HASH160 e399056c4ca63571aca44fc2d11b3fdac69a37e0 OP_ELSE 0 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 e399056c4ca63571aca44fc2d11b3fdac69a37e0 OP_ENDIF OP_EQUALVERIFY OP_CHECKSIG",
"hex": "63a820652c7dc687d98c9889304ed2e408c74b611e86a40caa51c4b43f1dd5913c5cd08876a914e399056c4ca63571aca44fc2d11b3fdac69a37e06700b17576a914e399056c4ca63571aca44fc2d11b3fdac69a37e06888ac",
"type": "nonstandard"
}
}
],
"outputs": [
{
}
],
"fee": 0.00001000
}
When I look at the inputs part of the PSBT, I can see that there is some input in there with my HTLC funds, and a scriptPubKey. Is this not the public key that the error is complaining doesn't exist?
From there I tried to sign it anyway using sats-connect:
const signPsbtOptions = {
payload: {
network: {
type: 'Testnet' // Change to 'Regtest' or 'Mainnet' as necessary
},
psbtBase64: `cHNidP8BAF4CAAAAAbPL7V1jyb+3R1UCjZ59ivvArJkc/+7bfxvA0QDjwJy+AAAAAAD+////AQAAAAAAAAAAIlEgmI+kZEmjRbl0oD6FTqJ7RKSipe+ZpSLIz0whDVrEu+MAAAAAAAEBK+gDAAAAAAAAIgAgpgjnxrbDIB0mCTFhbICxZdnAIvuWCkOZt5f+fZV3HMoBBVljqCBlLH3Gh9mMmIkwTtLkCMdLYR6GpAyqUcS0Px3VkTxc0Ih2qRTjmQVsTKY1caykT8LRGz/axpo34GcAsXV2qRTjmQVsTKY1caykT8LRGz/axpo34GiIrAAA`,
broadcast: false, // Set to true if you want to broadcast after signing
inputsToSign: [
{
address: "tb1pnz86gezf5dzmja9q86z5agnmgjj29f00nxjj9jx0fsss6kkyh03sjkqhpd", //should this be the address of signer or the address of the input?
signingIndexes: [0] // Assuming you want to sign the first input
}
],
},
onFinish: (response) => {
console.log('Signed PSBT:', response.psbtBase64);
// Here, you could add additional code to handle the signed PSBT
},
onCancel: () => alert('Signing canceled'),
};
try {
await signTransaction(signPsbtOptions);
} catch (error) {
console.error('Error signing PSBT:', error);
alert('Failed to sign PSBT.');
}
and I was met with the following error
Input script doesn't have pubKey
My Question
Why doesn't the input script have a public key, and isn't this the purpose of scriptPubKey? How do I provide the public key correctly to sign this psbt?
2.2.2
When I use the sats-connect api to build a sending transaction, the receiving address is TapRoot, and Xverse.app keeps prompting The transaction couldn’t proceed Request failed with status code 400,
Transaction broadcast successful
No response
No response
On the Xverse app's browser for iPhone, it seems that getAddress cannot be called from an iframe. However, using the exact same code, I am able to call getAddress from a PC. Version 1.3.0.
I would like to request 2 features:
Is there any function or endpoint to submit Txs that I finalize later with sats-connect?
Right now I am signing without broadcasting, finalizing, and then using external api for broadcast
When I access my webpage through the browser in the Xverse APP wallet and call the sendBtcTransaction function, I cannot receive any callback.
However, it can be used normally when calling signMessage and getAddress.
When accessing the same web page on a browser with the Xverse browser extension installed, all three functions work fine.
I observed that Unisat's inscription mint page can be used normally in Xverse APP. This is the URL: https://unisat.io/inscribe
Is it the way I'm using it that's wrong? Can anyone help me, thank you!
Using either request("signMessage", { ... })
or adapter.request("signMessage", { ... })
hangs with a ledger wallet connected. The promise is never resolved, even after confirming the signature on the ledger device.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.