sbtc-bridge-lib
Advanced tools
Comparing version 1.0.93 to 1.0.94
import * as btc from '@scure/btc-signer'; | ||
import type { Transaction } from '@scure/btc-signer'; | ||
import type { BridgeTransactionType, DepositPayloadUIType } from './types/sbtc_types.js'; | ||
@@ -6,4 +7,4 @@ export declare const revealPayment = 10001; | ||
/** | ||
* | ||
* @param network | ||
* buildOpReturnDepositTransaction:Transaction | ||
* @param network (devnet|testnet|mainnet) | ||
* @param uiPayload:DepositPayloadUIType | ||
@@ -13,12 +14,12 @@ * @param btcFeeRates current rates | ||
* @param stacksAddress the stacks address to materialise sBTC | ||
* @returns | ||
* @returns Transaction from @scure/btc-signer | ||
*/ | ||
export declare function buildOpReturnDepositTransaction(network: string, uiPayload: DepositPayloadUIType, btcFeeRates: any, addressInfo: any): btc.Transaction; | ||
export declare function buildOpReturnDepositTransaction(network: string, uiPayload: DepositPayloadUIType, btcFeeRates: any, addressInfo: any): Transaction; | ||
/** | ||
* @param network | ||
* @param uiPayload:DepositPayloadUIType | ||
* @param btcFeeRates current rates | ||
* @param addressInfo the utxos to spend from | ||
* @param commitTxAddress the commitment address - contains the taproot data and the payload | ||
* @returns transaction object | ||
* @param uiPayload | ||
* @param btcFeeRates | ||
* @param addressInfo | ||
* @param commitTxAddress | ||
* @returns Transaction from @scure/btc-signer | ||
*/ | ||
@@ -25,0 +26,0 @@ export declare function buildOpDropDepositTransaction(network: string, uiPayload: DepositPayloadUIType, btcFeeRates: any, addressInfo: any, commitTxAddress: string): btc.Transaction; |
@@ -12,4 +12,4 @@ import * as btc from '@scure/btc-signer'; | ||
/** | ||
* | ||
* @param network | ||
* buildOpReturnDepositTransaction:Transaction | ||
* @param network (devnet|testnet|mainnet) | ||
* @param uiPayload:DepositPayloadUIType | ||
@@ -19,3 +19,3 @@ * @param btcFeeRates current rates | ||
* @param stacksAddress the stacks address to materialise sBTC | ||
* @returns | ||
* @returns Transaction from @scure/btc-signer | ||
*/ | ||
@@ -40,7 +40,7 @@ export function buildOpReturnDepositTransaction(network, uiPayload, btcFeeRates, addressInfo) { | ||
* @param network | ||
* @param uiPayload:DepositPayloadUIType | ||
* @param btcFeeRates current rates | ||
* @param addressInfo the utxos to spend from | ||
* @param commitTxAddress the commitment address - contains the taproot data and the payload | ||
* @returns transaction object | ||
* @param uiPayload | ||
* @param btcFeeRates | ||
* @param addressInfo | ||
* @param commitTxAddress | ||
* @returns Transaction from @scure/btc-signer | ||
*/ | ||
@@ -47,0 +47,0 @@ export function buildOpDropDepositTransaction(network, uiPayload, btcFeeRates, addressInfo, commitTxAddress) { |
@@ -18,3 +18,3 @@ import type { PayloadType } from './types/sbtc_types.js'; | ||
export declare function bigUint64ToAmount(buf: Uint8Array): number; | ||
export declare function parseWithdrawalPayload(network: string, d1: Uint8Array, scriptPubKey: string): PayloadType; | ||
export declare function parseWithdrawalPayload(network: string, d1: Uint8Array, bitcoinAddress: string): PayloadType; | ||
export declare enum PrincipalType { | ||
@@ -24,4 +24,27 @@ STANDARD = "05", | ||
} | ||
/** | ||
* | ||
* @param net | ||
* @param address | ||
* @returns | ||
*/ | ||
export declare function buildDepositPayloadOpReturn(net: any, address: string): Uint8Array; | ||
/** | ||
* | ||
* @param net | ||
* @param amountSats | ||
* @param address | ||
* @param opDrop | ||
* @param memo | ||
* @returns | ||
*/ | ||
export declare function buildDepositPayload(net: any, amountSats: number, address: string, opDrop: boolean, memo: string | undefined): Uint8Array; | ||
/** | ||
* | ||
* @param net | ||
* @param amount | ||
* @param signature | ||
* @param opDrop | ||
* @returns | ||
*/ | ||
export declare function buildWithdrawalPayload(net: any, amount: number, signature: Uint8Array, opDrop: boolean): Uint8Array; | ||
@@ -75,2 +98,8 @@ /** | ||
export declare function readDepositValue(outputs: Array<any>): number; | ||
/** | ||
* | ||
* @param network | ||
* @param txHex | ||
* @returns | ||
*/ | ||
export declare function parsePayloadFromTransaction(network: string, txHex: string): PayloadType; | ||
@@ -119,4 +148,17 @@ export declare function parsePayloadFromOutput(network: string, out0: any, scriptPubKey: string): PayloadType; | ||
*/ | ||
/** | ||
* | ||
* @param network | ||
* @param amount | ||
* @param bitcoinAddress | ||
* @returns | ||
*/ | ||
export declare function getDataToSign(network: string, amount: number, bitcoinAddress: string): Uint8Array; | ||
export declare function getStacksSimpleHashOfDataToSign(network: string, amount: number, bitcoinAddress: string): string; | ||
/** | ||
* | ||
* @param messageHash | ||
* @param signature | ||
* @returns | ||
*/ | ||
export declare function getStacksAddressFromSignature(messageHash: Uint8Array, signature: string): { | ||
@@ -140,2 +182,7 @@ tp2pkh: string; | ||
export declare function fromStorable(script: any): any; | ||
/** | ||
* | ||
* @param script | ||
* @returns | ||
*/ | ||
export declare function toStorable(script: any): { | ||
@@ -142,0 +189,0 @@ address: any; |
@@ -129,10 +129,10 @@ import * as secp from '@noble/secp256k1'; | ||
} | ||
export function parseWithdrawalPayload(network, d1, scriptPubKey) { | ||
export function parseWithdrawalPayload(network, d1, bitcoinAddress) { | ||
const magicOp = getMagicAndOpCode(d1); | ||
if (magicOp.magic) { | ||
return parseWithdrawalPayloadNoMagic(network, d1.subarray(2), scriptPubKey); | ||
return parseWithdrawalPayloadNoMagic(network, d1.subarray(2), bitcoinAddress); | ||
} | ||
return parseWithdrawalPayloadNoMagic(network, d1, scriptPubKey); | ||
return parseWithdrawalPayloadNoMagic(network, d1, bitcoinAddress); | ||
} | ||
function parseWithdrawalPayloadNoMagic(network, d1, scriptPubKey) { | ||
function parseWithdrawalPayloadNoMagic(network, d1, bitcoinAddress) { | ||
//console.log('parseWithdrawalPayloadNoMagic: d1: ', hex.encode(d1)) | ||
@@ -150,7 +150,8 @@ const opcode = hex.encode(d1.subarray(0, 1)).toUpperCase(); | ||
//if (signature.startsWith('00')) signature = reverseSigBits(signature) | ||
//console.log('parseWithdrawalPayloadNoMagic signature: ', signature) | ||
const msgHash = getStacksSimpleHashOfDataToSign(network, amountSats, scriptPubKey); | ||
//console.log('parseWithdrawalPayloadNoMagic msgHash: ' + msgHash) | ||
console.log('parseWithdrawalPayloadNoMagic bitcoinAddress: ', bitcoinAddress); | ||
console.log('parseWithdrawalPayloadNoMagic signature: ', signature); | ||
const msgHash = getStacksSimpleHashOfDataToSign(network, amountSats, bitcoinAddress); | ||
console.log('parseWithdrawalPayloadNoMagic msgHash: ' + msgHash); | ||
const pubKey = getPubkeySignature(hex.decode(msgHash), signature); | ||
//console.log('parseWithdrawalPayloadNoMagic pubKey: ' + hex.encode(pubKey)) | ||
console.log('parseWithdrawalPayloadNoMagic pubKey: ' + hex.encode(pubKey)); | ||
const v = verifyMessageSignature({ signature, message: msgHash, publicKey: hex.encode(pubKey) }); | ||
@@ -175,2 +176,8 @@ //console.log('parseWithdrawalPayloadNoMagic v: ' + v) | ||
})(PrincipalType || (PrincipalType = {})); | ||
/** | ||
* | ||
* @param net | ||
* @param address | ||
* @returns | ||
*/ | ||
export function buildDepositPayloadOpReturn(net, address) { | ||
@@ -198,2 +205,11 @@ const magicBuf = (typeof net === 'object' && net.bech32 === 'tb') ? hex.decode(MAGIC_BYTES_TESTNET) : hex.decode(MAGIC_BYTES_MAINNET); | ||
} | ||
/** | ||
* | ||
* @param net | ||
* @param amountSats | ||
* @param address | ||
* @param opDrop | ||
* @param memo | ||
* @returns | ||
*/ | ||
export function buildDepositPayload(net, amountSats, address, opDrop, memo) { | ||
@@ -237,2 +253,10 @@ const magicBuf = (typeof net === 'object' && net.bech32 === 'tb') ? hex.decode(MAGIC_BYTES_TESTNET) : hex.decode(MAGIC_BYTES_MAINNET); | ||
} | ||
/** | ||
* | ||
* @param net | ||
* @param amount | ||
* @param signature | ||
* @param opDrop | ||
* @returns | ||
*/ | ||
export function buildWithdrawalPayload(net, amount, signature, opDrop) { | ||
@@ -304,2 +328,8 @@ const magicBuf = (net === btc.TEST_NETWORK) ? hex.decode(MAGIC_BYTES_TESTNET) : hex.decode(MAGIC_BYTES_MAINNET); | ||
} | ||
/** | ||
* | ||
* @param network | ||
* @param txHex | ||
* @returns | ||
*/ | ||
export function parsePayloadFromTransaction(network, txHex) { | ||
@@ -378,2 +408,9 @@ const tx = btc.Transaction.fromRaw(hex.decode(txHex), { allowUnknowInput: true, allowUnknowOutput: true, allowUnknownOutputs: true, allowUnknownInputs: true }); | ||
*/ | ||
/** | ||
* | ||
* @param network | ||
* @param amount | ||
* @param bitcoinAddress | ||
* @returns | ||
*/ | ||
export function getDataToSign(network, amount, bitcoinAddress) { | ||
@@ -391,2 +428,4 @@ const net = (network === 'testnet') ? btc.TEST_NETWORK : btc.NETWORK; | ||
const msgHash = hashMessage(hex.encode(dataToSign)); | ||
console.log('getStacksSimpleHashOfDataToSign:dataToSign: ' + hex.encode(dataToSign)); | ||
console.log('getStacksSimpleHashOfDataToSign:msgHash: ' + hex.encode(msgHash)); | ||
return hex.encode(msgHash); | ||
@@ -406,36 +445,16 @@ } | ||
function getPubkeySignature(messageHash, signature) { | ||
//console.log('getStacksAddressFromSignature: messageHash: ' + hex.encode(messageHash)) | ||
//console.log('getStacksAddressFromSignature: signature: ' + signature) | ||
let pubkey; | ||
try { | ||
//console.log('=============================================================') | ||
const recBits = (signature.substring(signature.length - 2)); | ||
//let signature = signature.substring(2) | ||
//console.log('getPubkeySignature1: recBits: ' + ' ' + recBits) | ||
// works for Hiro sig but not unit test sig ? | ||
const sigM = recoverSignature({ signature: signature, mode: 'rsv' }); // vrs to rsv | ||
let sig = new secp.Signature(sigM.signature.r, sigM.signature.s); | ||
sig = sig.addRecoveryBit(Number(recBits)); // sometime 0 sometiimes 1 ?? | ||
//console.log('getPubkeySignature1: recovery: ', sig) | ||
const pubkeyM = sig.recoverPublicKey(messageHash); | ||
//console.log('getPubkeySignature11: Hiro: messageHash: ' + hex.encode(messageHash)) | ||
pubkey = hex.decode(pubkeyM.toHex()); | ||
//console.log('getPubkeySignature11: Hiro: pubkey: ' + hex.encode(pubkey)) | ||
} | ||
catch (err) { | ||
//console.log('=============================================================') | ||
//console.log('getPubkeySignature2: error: ' + ' ' + err.message) | ||
const recBits = (signature.substring(0, 2)); | ||
const sigM = recoverSignature({ signature: signature, mode: 'rsv' }); // vrs to rsv | ||
//console.log('getPubkeySignature2: sigM: ', sigM) | ||
let sig = new secp.Signature(sigM.signature.r, sigM.signature.s); | ||
sig = sig.addRecoveryBit(Number(recBits)); // sometime 0 sometiimes 1 ?? | ||
//console.log('getPubkeySignature2: recovery: ', sig) | ||
const pubkeyM = sig.recoverPublicKey(messageHash); | ||
//console.log('getPubkeySignature2: Hiro: messageHash: ' + hex.encode(messageHash)) | ||
pubkey = hex.decode(pubkeyM.toHex()); | ||
//console.log('getPubkeySignature2: Hiro: pubkey: ' + hex.encode(pubkey)) | ||
} | ||
const sigM = recoverSignature({ signature: signature, mode: 'vrs' }); // vrs to rsv | ||
let sig = new secp.Signature(sigM.signature.r, sigM.signature.s); | ||
sig = sig.addRecoveryBit(0); | ||
const pubkeyM = sig.recoverPublicKey(messageHash); | ||
const pubkey = hex.decode(pubkeyM.toHex()); | ||
console.log(pubkeyM.toHex()); | ||
return pubkey; | ||
} | ||
/** | ||
* | ||
* @param messageHash | ||
* @param signature | ||
* @returns | ||
*/ | ||
export function getStacksAddressFromSignature(messageHash, signature) { | ||
@@ -452,3 +471,3 @@ const pubkey = getPubkeySignature(messageHash, signature); | ||
}; | ||
//console.log('getStacksAddressFromSignature: addresses: ', addresses) | ||
console.log('getStacksAddressFromSignature: addresses: ', addresses); | ||
return addresses; | ||
@@ -495,2 +514,7 @@ } | ||
} | ||
/** | ||
* | ||
* @param script | ||
* @returns | ||
*/ | ||
export function toStorable(script) { | ||
@@ -497,0 +521,0 @@ //const copied = JSON.parse(JSON.stringify(script)); |
@@ -88,5 +88,22 @@ import * as btc from '@scure/btc-signer'; | ||
export declare function addInputs(network: string, amount: number, revealPayment: number, transaction: btc.Transaction, feeCalc: boolean, utxos: Array<UTXO>, paymentPublicKey: string): void; | ||
/** | ||
* getAddressFromOutScript converts a script to an address | ||
* @param network:string | ||
* @param script: Uint8Array | ||
* @returns address as string | ||
*/ | ||
export declare function getAddressFromOutScript(network: string, script: Uint8Array): string; | ||
export declare function inputAmt(tx: btc.Transaction): number; | ||
/** | ||
* | ||
* @param pubkey | ||
* @returns | ||
*/ | ||
export declare function toXOnly(pubkey: string): string; | ||
export declare function getPegWalletAddressFromPublicKey(network: string, sbtcWalletPublicKey: string): string; | ||
/** | ||
* | ||
* @param network | ||
* @param sbtcWalletPublicKey | ||
* @returns | ||
*/ | ||
export declare function getPegWalletAddressFromPublicKey(network: string, sbtcWalletPublicKey: string): string | undefined; |
@@ -288,2 +288,8 @@ import * as secp from '@noble/secp256k1'; | ||
} | ||
/** | ||
* getAddressFromOutScript converts a script to an address | ||
* @param network:string | ||
* @param script: Uint8Array | ||
* @returns address as string | ||
*/ | ||
export function getAddressFromOutScript(network, script) { | ||
@@ -357,6 +363,19 @@ const net = (network === 'testnet') ? btc.TEST_NETWORK : btc.NETWORK; | ||
} | ||
/** | ||
* | ||
* @param pubkey | ||
* @returns | ||
*/ | ||
export function toXOnly(pubkey) { | ||
return hex.encode(hex.decode(pubkey).subarray(1, 33)); | ||
} | ||
/** | ||
* | ||
* @param network | ||
* @param sbtcWalletPublicKey | ||
* @returns | ||
*/ | ||
export function getPegWalletAddressFromPublicKey(network, sbtcWalletPublicKey) { | ||
if (!sbtcWalletPublicKey) | ||
return; | ||
let net = (network === 'testnet') ? btc.TEST_NETWORK : btc.NETWORK; | ||
@@ -363,0 +382,0 @@ if (network === 'development' || network === 'simnet') { |
@@ -5,3 +5,20 @@ import * as btc from '@scure/btc-signer'; | ||
export declare const dust = 500; | ||
/** | ||
* | ||
* @param network | ||
* @param uiPayload | ||
* @param addressInfo | ||
* @param btcFeeRates | ||
* @returns Transaction from @scure/btc-signer | ||
*/ | ||
export declare function buildOpReturnWithdrawTransaction(network: string, uiPayload: WithdrawPayloadUIType, addressInfo: any, btcFeeRates: any): btc.Transaction; | ||
/** | ||
* | ||
* @param network | ||
* @param uiPayload | ||
* @param addressInfo | ||
* @param btcFeeRates | ||
* @param originator | ||
* @returns | ||
*/ | ||
export declare function buildOpDropWithdrawTransaction(network: string, uiPayload: WithdrawPayloadUIType, addressInfo: any, btcFeeRates: any, originator: string): btc.Transaction; | ||
@@ -8,0 +25,0 @@ export declare function calculateWithdrawFees(network: string, opDrop: boolean, addressInfo: any, amount: number, feeInfo: { |
@@ -11,2 +11,10 @@ import * as btc from '@scure/btc-signer'; | ||
export const dust = 500; | ||
/** | ||
* | ||
* @param network | ||
* @param uiPayload | ||
* @param addressInfo | ||
* @param btcFeeRates | ||
* @returns Transaction from @scure/btc-signer | ||
*/ | ||
export function buildOpReturnWithdrawTransaction(network, uiPayload, addressInfo, btcFeeRates) { | ||
@@ -28,2 +36,11 @@ if (!uiPayload.signature) | ||
} | ||
/** | ||
* | ||
* @param network | ||
* @param uiPayload | ||
* @param addressInfo | ||
* @param btcFeeRates | ||
* @param originator | ||
* @returns | ||
*/ | ||
export function buildOpDropWithdrawTransaction(network, uiPayload, addressInfo, btcFeeRates, originator) { | ||
@@ -30,0 +47,0 @@ if (!uiPayload.signature) |
{ | ||
"name": "sbtc-bridge-lib", | ||
"version": "1.0.93", | ||
"version": "1.0.94", | ||
"description": "Library for sBTC Bridge web client and API apps ", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
167
README.md
@@ -1,29 +0,168 @@ | ||
# sbtc-bridge-lib | ||
# SBTC SDK Documentation | ||
 | ||
Decentralised protocol for depositing and withdrawing bitcoin on the Stacks blockchain. | ||
This library is intended to be used by app developers to build sBTC applications. | ||
## Introduction | ||
For more information on the sBTC project see; | ||
Library and utility functions for the sBTC Bridge. | ||
- [sBTC.tech](https://sbtc.tech) | ||
- [sBTC bridge web app](https://bridge.sbtc.tech?net=testnet) | ||
- [npm registry](https://www.npmjs.com/package/sbtc-bridge-lib) | ||
[sbtc.tech](https://sbtc.tech). | ||
## The sBTC Library Install | ||
## Build | ||
The sbtc-bridge-lib can be installed via npm registry; | ||
```bash | ||
npm install | ||
npx tsc | ||
npm install sbtc-bridge-lib | ||
``` | ||
## Test | ||
### Build & Publish | ||
```bash | ||
npm run test | ||
npm install sbtc-bridge-lib | ||
npm install | ||
npx tsc | ||
npm publish | ||
``` | ||
## Publish | ||
### The sBTC Library Modules | ||
```bash | ||
npm publish | ||
``` | ||
- deposit_utils.ts | ||
- payload_utils.ts | ||
- wallet_utils.ts | ||
- withdraw_utils.ts | ||
#### deposit_utils.ts | ||
**buildOpReturnDepositTransaction** | ||
Builds the PSBT the user signs to initiate deposit via op_return | ||
- @param network (devnet|testnet|mainnet) | ||
- @param uiPayload:DepositPayloadUIType | ||
- @param btcFeeRates current rates | ||
- @param addressInfo the utxos to spend from | ||
- @param stacksAddress the stacks address to materialise sBTC | ||
- @returns Transaction from @scure/btc-signer | ||
**buildOpDropDepositTransaction** | ||
Builds the PSBT the user signs to initiate deposit via op_drop | ||
- @param network | ||
- @param uiPayload:DepositPayloadUIType | ||
- @param btcFeeRates | ||
- @param addressInfo | ||
- @param commitTxAddress | ||
- @returns Transaction from @scure/btc-signer | ||
#### withdraw_utils.ts | ||
**buildOpReturnWithdrawTransaction** | ||
Builds the PSBT the user signs to initiate withdrawal via op_return | ||
- @param network | ||
- @param uiPayload:WithdrawPayloadUIType | ||
- @param btcFeeRates | ||
- @param addressInfo | ||
- @param commitTxAddress | ||
- @returns Transaction from @scure/btc-signer | ||
**buildOpDropWithdrawTransaction** | ||
Builds the PSBT the user signs to initiate withdrawal via op_drop | ||
- @param network | ||
- @param uiPayload :WithdrawPayloadUIType | ||
- @param addressInfo | ||
- @param btcFeeRates | ||
- @param originator | ||
- @returns Transaction from @scure/btc-signer | ||
#### payload_utils.ts | ||
**buildDepositPayload** | ||
Builds the data to be transmitted in a deposit request | ||
- @param net | ||
- @param amountSats | ||
- @param address | ||
- @param opDrop | ||
- @param memo | ||
- @returns Uint8Array | ||
**buildWithdrawalPayload** | ||
Builds the data to be transmitted in a withdraw request | ||
- @param net | ||
- @param amount | ||
- @param signature | ||
- @param opDrop | ||
- @returns Uint8Array | ||
**parsePayloadFromTransaction** | ||
Takes raw transaction hex extracts the sBTC data and returns it in a PayloadType | ||
- @param network | ||
- @param txHex | ||
- @returns PayloadType | ||
**getDataToSign** | ||
The data the user needs to sign to issue a withdrawal request | ||
- @param network | ||
- @param amount | ||
- @param bitcoinAddress | ||
- @returns Uint8Array | ||
**getStacksAddressFromSignature** | ||
- @param messageHash | ||
- @param signature | ||
- @returns string | ||
**toStorable** | ||
Converts taproot script and leaf data structure to hex for easy storage. | ||
- @param script | ||
- @returns CommitmentScriptDataType | ||
**fromStorable** | ||
Creates a deep clone of the taproot script path data. | ||
- @param script | ||
- @returns CommitmentScriptDataType | ||
#### wallet_utils.ts | ||
**getAddressFromOutScript** | ||
getAddressFromOutScript converts a script to an address | ||
- @param network:string | ||
- @param script: Uint8Array | ||
- @returns address as string | ||
**toXOnly** | ||
converts compressed public key to x-only form for schnorr compatibility | ||
- @param pubkey | ||
- @returns pubkey as string | ||
**getPegWalletAddressFromPublicKey** | ||
Converts the sBTC peg wallet public key to a taproot segwit v2 address. | ||
- @param network | ||
- @param sbtcWalletPublicKey | ||
- @returns address as string |
@@ -5,2 +5,3 @@ import * as btc from '@scure/btc-signer'; | ||
import { hex } from '@scure/base'; | ||
import type { Transaction } from '@scure/btc-signer' | ||
import type { BridgeTransactionType, DepositPayloadUIType, UTXO } from './types/sbtc_types.js' | ||
@@ -15,5 +16,6 @@ import { toStorable, buildDepositPayload } from './payload_utils.js' | ||
export const dust = 500; | ||
/** | ||
* | ||
* @param network | ||
* buildOpReturnDepositTransaction:Transaction | ||
* @param network (devnet|testnet|mainnet) | ||
* @param uiPayload:DepositPayloadUIType | ||
@@ -23,5 +25,5 @@ * @param btcFeeRates current rates | ||
* @param stacksAddress the stacks address to materialise sBTC | ||
* @returns | ||
* @returns Transaction from @scure/btc-signer | ||
*/ | ||
export function buildOpReturnDepositTransaction(network:string, uiPayload:DepositPayloadUIType, btcFeeRates:any, addressInfo:any) { | ||
export function buildOpReturnDepositTransaction(network:string, uiPayload:DepositPayloadUIType, btcFeeRates:any, addressInfo:any):Transaction { | ||
const net = (network === 'testnet') ? btc.TEST_NETWORK : btc.NETWORK; | ||
@@ -32,3 +34,3 @@ const sbtcWalletAddress = getPegWalletAddressFromPublicKey(network, uiPayload.sbtcWalletPublicKey) | ||
const txFees = calculateDepositFees(network, false, uiPayload.amountSats, btcFeeRates.feeInfo, addressInfo, sbtcWalletAddress, data) | ||
const txFees = calculateDepositFees(network, false, uiPayload.amountSats, btcFeeRates.feeInfo, addressInfo, sbtcWalletAddress!, data) | ||
const tx = new btc.Transaction({ allowUnknowInput: true, allowUnknowOutput: true, allowUnknownInputs:true, allowUnknownOutputs:true }); | ||
@@ -38,3 +40,3 @@ // no reveal fee for op_return | ||
tx.addOutput({ script: btc.Script.encode(['RETURN', data]), amount: BigInt(0) }); | ||
tx.addOutputAddress(sbtcWalletAddress, BigInt(uiPayload.amountSats), net); | ||
tx.addOutputAddress(sbtcWalletAddress!, BigInt(uiPayload.amountSats), net); | ||
const changeAmount = inputAmt(tx) - (uiPayload.amountSats + txFees[1]); | ||
@@ -47,7 +49,7 @@ if (changeAmount > 0) tx.addOutputAddress(uiPayload.bitcoinAddress, BigInt(changeAmount), net); | ||
* @param network | ||
* @param uiPayload:DepositPayloadUIType | ||
* @param btcFeeRates current rates | ||
* @param addressInfo the utxos to spend from | ||
* @param commitTxAddress the commitment address - contains the taproot data and the payload | ||
* @returns transaction object | ||
* @param uiPayload | ||
* @param btcFeeRates | ||
* @param addressInfo | ||
* @param commitTxAddress | ||
* @returns Transaction from @scure/btc-signer | ||
*/ | ||
@@ -54,0 +56,0 @@ export function buildOpDropDepositTransaction (network:string, uiPayload:DepositPayloadUIType, btcFeeRates:any, addressInfo:any, commitTxAddress:string) { |
@@ -146,11 +146,11 @@ import * as secp from '@noble/secp256k1'; | ||
export function parseWithdrawalPayload(network:string, d1:Uint8Array, scriptPubKey:string):PayloadType { | ||
export function parseWithdrawalPayload(network:string, d1:Uint8Array, bitcoinAddress:string):PayloadType { | ||
const magicOp = getMagicAndOpCode(d1); | ||
if (magicOp.magic) { | ||
return parseWithdrawalPayloadNoMagic(network, d1.subarray(2), scriptPubKey); | ||
return parseWithdrawalPayloadNoMagic(network, d1.subarray(2), bitcoinAddress); | ||
} | ||
return parseWithdrawalPayloadNoMagic(network, d1, scriptPubKey); | ||
return parseWithdrawalPayloadNoMagic(network, d1, bitcoinAddress); | ||
} | ||
function parseWithdrawalPayloadNoMagic(network:string, d1:Uint8Array, scriptPubKey:string):PayloadType { | ||
function parseWithdrawalPayloadNoMagic(network:string, d1:Uint8Array, bitcoinAddress:string):PayloadType { | ||
//console.log('parseWithdrawalPayloadNoMagic: d1: ', hex.encode(d1)) | ||
@@ -168,8 +168,9 @@ const opcode = hex.encode(d1.subarray(0,1)).toUpperCase(); | ||
//if (signature.startsWith('00')) signature = reverseSigBits(signature) | ||
//console.log('parseWithdrawalPayloadNoMagic signature: ', signature) | ||
console.log('parseWithdrawalPayloadNoMagic bitcoinAddress: ', bitcoinAddress) | ||
console.log('parseWithdrawalPayloadNoMagic signature: ', signature) | ||
const msgHash = getStacksSimpleHashOfDataToSign(network, amountSats, scriptPubKey); | ||
//console.log('parseWithdrawalPayloadNoMagic msgHash: ' + msgHash) | ||
const msgHash = getStacksSimpleHashOfDataToSign(network, amountSats, bitcoinAddress); | ||
console.log('parseWithdrawalPayloadNoMagic msgHash: ' + msgHash) | ||
const pubKey = getPubkeySignature(hex.decode(msgHash), signature) | ||
//console.log('parseWithdrawalPayloadNoMagic pubKey: ' + hex.encode(pubKey)) | ||
console.log('parseWithdrawalPayloadNoMagic pubKey: ' + hex.encode(pubKey)) | ||
const v = verifyMessageSignature({ signature, message: msgHash, publicKey: hex.encode(pubKey) }) | ||
@@ -196,2 +197,8 @@ //console.log('parseWithdrawalPayloadNoMagic v: ' + v) | ||
/** | ||
* | ||
* @param net | ||
* @param address | ||
* @returns | ||
*/ | ||
export function buildDepositPayloadOpReturn(net:any, address:string):Uint8Array { | ||
@@ -220,2 +227,11 @@ const magicBuf = (typeof net === 'object' && net.bech32 === 'tb') ? hex.decode(MAGIC_BYTES_TESTNET) : hex.decode(MAGIC_BYTES_MAINNET); | ||
/** | ||
* | ||
* @param net | ||
* @param amountSats | ||
* @param address | ||
* @param opDrop | ||
* @param memo | ||
* @returns | ||
*/ | ||
export function buildDepositPayload(net:any, amountSats:number, address:string, opDrop:boolean, memo:string|undefined):Uint8Array { | ||
@@ -260,2 +276,10 @@ const magicBuf = (typeof net === 'object' && net.bech32 === 'tb') ? hex.decode(MAGIC_BYTES_TESTNET) : hex.decode(MAGIC_BYTES_MAINNET); | ||
/** | ||
* | ||
* @param net | ||
* @param amount | ||
* @param signature | ||
* @param opDrop | ||
* @returns | ||
*/ | ||
export function buildWithdrawalPayload(net:any, amount:number, signature:Uint8Array, opDrop:boolean):Uint8Array { | ||
@@ -327,2 +351,8 @@ const magicBuf = (net === btc.TEST_NETWORK) ? hex.decode(MAGIC_BYTES_TESTNET) : hex.decode(MAGIC_BYTES_MAINNET); | ||
/** | ||
* | ||
* @param network | ||
* @param txHex | ||
* @returns | ||
*/ | ||
export function parsePayloadFromTransaction(network:string, txHex:string):PayloadType { | ||
@@ -403,2 +433,9 @@ const tx:btc.Transaction = btc.Transaction.fromRaw(hex.decode(txHex), {allowUnknowInput:true, allowUnknowOutput: true, allowUnknownOutputs: true, allowUnknownInputs: true}) | ||
/** | ||
* | ||
* @param network | ||
* @param amount | ||
* @param bitcoinAddress | ||
* @returns | ||
*/ | ||
export function getDataToSign(network:string, amount:number, bitcoinAddress:string):Uint8Array { | ||
@@ -417,2 +454,4 @@ const net = (network === 'testnet') ? btc.TEST_NETWORK : btc.NETWORK; | ||
const msgHash = hashMessage(hex.encode(dataToSign)); | ||
console.log('getStacksSimpleHashOfDataToSign:dataToSign: ' + hex.encode(dataToSign)) | ||
console.log('getStacksSimpleHashOfDataToSign:msgHash: ' + hex.encode(msgHash)) | ||
return hex.encode(msgHash); | ||
@@ -434,38 +473,17 @@ } | ||
function getPubkeySignature(messageHash:Uint8Array, signature:string) { | ||
//console.log('getStacksAddressFromSignature: messageHash: ' + hex.encode(messageHash)) | ||
//console.log('getStacksAddressFromSignature: signature: ' + signature) | ||
let pubkey; | ||
try { | ||
//console.log('=============================================================') | ||
const recBits = (signature.substring(signature.length - 2)); | ||
//let signature = signature.substring(2) | ||
//console.log('getPubkeySignature1: recBits: ' + ' ' + recBits) | ||
// works for Hiro sig but not unit test sig ? | ||
const sigM = recoverSignature({ signature: signature, mode: 'rsv' }); // vrs to rsv | ||
let sig = new secp.Signature(sigM.signature.r, sigM.signature.s); | ||
sig = sig.addRecoveryBit(Number(recBits)); // sometime 0 sometiimes 1 ?? | ||
//console.log('getPubkeySignature1: recovery: ', sig) | ||
const pubkeyM = sig.recoverPublicKey(messageHash); | ||
//console.log('getPubkeySignature11: Hiro: messageHash: ' + hex.encode(messageHash)) | ||
pubkey = hex.decode(pubkeyM.toHex()); | ||
//console.log('getPubkeySignature11: Hiro: pubkey: ' + hex.encode(pubkey)) | ||
} catch (err:any) { | ||
//console.log('=============================================================') | ||
//console.log('getPubkeySignature2: error: ' + ' ' + err.message) | ||
const recBits = (signature.substring(0, 2)); | ||
const sigM = recoverSignature({ signature: signature, mode: 'rsv' }); // vrs to rsv | ||
//console.log('getPubkeySignature2: sigM: ', sigM) | ||
let sig = new secp.Signature(sigM.signature.r, sigM.signature.s); | ||
sig = sig.addRecoveryBit(Number(recBits)); // sometime 0 sometiimes 1 ?? | ||
//console.log('getPubkeySignature2: recovery: ', sig) | ||
const pubkeyM = sig.recoverPublicKey(messageHash); | ||
//console.log('getPubkeySignature2: Hiro: messageHash: ' + hex.encode(messageHash)) | ||
pubkey = hex.decode(pubkeyM.toHex()); | ||
//console.log('getPubkeySignature2: Hiro: pubkey: ' + hex.encode(pubkey)) | ||
} | ||
return pubkey | ||
const sigM = recoverSignature({ signature: signature, mode: 'vrs' }); // vrs to rsv | ||
let sig = new secp.Signature(sigM.signature.r, sigM.signature.s); | ||
sig = sig.addRecoveryBit(0); | ||
const pubkeyM = sig.recoverPublicKey(messageHash); | ||
const pubkey = hex.decode(pubkeyM.toHex()); | ||
console.log(pubkeyM.toHex()) | ||
return pubkey; | ||
} | ||
/** | ||
* | ||
* @param messageHash | ||
* @param signature | ||
* @returns | ||
*/ | ||
export function getStacksAddressFromSignature(messageHash:Uint8Array, signature:string) { | ||
@@ -483,3 +501,3 @@ const pubkey = getPubkeySignature(messageHash, signature) | ||
} | ||
//console.log('getStacksAddressFromSignature: addresses: ', addresses) | ||
console.log('getStacksAddressFromSignature: addresses: ', addresses) | ||
return addresses; | ||
@@ -530,3 +548,8 @@ } | ||
} | ||
/** | ||
* | ||
* @param script | ||
* @returns | ||
*/ | ||
export function toStorable(script:any) { | ||
@@ -533,0 +556,0 @@ //const copied = JSON.parse(JSON.stringify(script)); |
@@ -32,3 +32,3 @@ import * as btc from '@scure/btc-signer'; | ||
if (!script.tapInternalKey) throw new Error('Incorrect data passed') | ||
const sbtcWalletAddrScript = btc.Address(net).decode(outAddr) | ||
const sbtcWalletAddrScript = btc.Address(net).decode(outAddr!) | ||
if (sbtcWalletAddrScript.type !== 'tr') throw new Error('Taproot required') | ||
@@ -136,3 +136,3 @@ //const fromBtcAddressScript = btc.Address(net).decode(peginRequest.uiPayload.bitcoinAddress); | ||
*/ | ||
tx.addOutputAddress(outAddr, BigInt(amount), net); | ||
tx.addOutputAddress(outAddr!, BigInt(amount), net); | ||
@@ -139,0 +139,0 @@ /** |
@@ -281,3 +281,9 @@ import * as secp from '@noble/secp256k1'; | ||
export function getAddressFromOutScript(network:string, script: Uint8Array) { | ||
/** | ||
* getAddressFromOutScript converts a script to an address | ||
* @param network:string | ||
* @param script: Uint8Array | ||
* @returns address as string | ||
*/ | ||
export function getAddressFromOutScript(network:string, script: Uint8Array):string { | ||
const net = (network === 'testnet') ? btc.TEST_NETWORK : btc.NETWORK; | ||
@@ -353,2 +359,7 @@ const outputScript = btc.OutScript.decode(script); | ||
/** | ||
* | ||
* @param pubkey | ||
* @returns | ||
*/ | ||
export function toXOnly(pubkey: string): string { | ||
@@ -358,3 +369,10 @@ return hex.encode(hex.decode(pubkey).subarray(1, 33)) | ||
/** | ||
* | ||
* @param network | ||
* @param sbtcWalletPublicKey | ||
* @returns | ||
*/ | ||
export function getPegWalletAddressFromPublicKey (network:string, sbtcWalletPublicKey:string) { | ||
if (!sbtcWalletPublicKey) return | ||
let net = (network === 'testnet') ? btc.TEST_NETWORK : btc.NETWORK; | ||
@@ -361,0 +379,0 @@ if (network === 'development' || network === 'simnet') { |
@@ -16,2 +16,10 @@ import * as btc from '@scure/btc-signer'; | ||
/** | ||
* | ||
* @param network | ||
* @param uiPayload | ||
* @param addressInfo | ||
* @param btcFeeRates | ||
* @returns Transaction from @scure/btc-signer | ||
*/ | ||
export function buildOpReturnWithdrawTransaction(network:string, uiPayload:WithdrawPayloadUIType, addressInfo:any, btcFeeRates:any) { | ||
@@ -22,3 +30,3 @@ if (!uiPayload.signature) throw new Error('Signature of output 2 scriptPubKey is required'); | ||
const data = buildData(network, uiPayload.amountSats, uiPayload.signature, false) | ||
const txFees = calculateWithdrawFees(network, false, addressInfo, uiPayload.amountSats, btcFeeRates, sbtcWalletAddress, uiPayload.bitcoinAddress, uiPayload.paymentPublicKey, data) | ||
const txFees = calculateWithdrawFees(network, false, addressInfo, uiPayload.amountSats, btcFeeRates, sbtcWalletAddress!, uiPayload.bitcoinAddress, uiPayload.paymentPublicKey, data) | ||
const tx = new btc.Transaction({ allowUnknowOutput: true, allowUnknownInputs:true, allowUnknownOutputs:true }); | ||
@@ -33,2 +41,11 @@ addInputs(network, uiPayload.amountSats, 0, tx, false, addressInfo.utxos, uiPayload.paymentPublicKey); | ||
/** | ||
* | ||
* @param network | ||
* @param uiPayload | ||
* @param addressInfo | ||
* @param btcFeeRates | ||
* @param originator | ||
* @returns | ||
*/ | ||
export function buildOpDropWithdrawTransaction (network:string, uiPayload:WithdrawPayloadUIType, addressInfo:any, btcFeeRates:any, originator:string) { | ||
@@ -38,3 +55,3 @@ if (!uiPayload.signature) throw new Error('Signature of output 2 scriptPubKey is required'); | ||
const sbtcWalletAddress = getPegWalletAddressFromPublicKey(network, uiPayload.sbtcWalletPublicKey) | ||
const txFees = calculateWithdrawFees(network, true, addressInfo, uiPayload.amountSats, btcFeeRates, sbtcWalletAddress, uiPayload.bitcoinAddress, uiPayload.paymentPublicKey, undefined) | ||
const txFees = calculateWithdrawFees(network, true, addressInfo, uiPayload.amountSats, btcFeeRates, sbtcWalletAddress!, uiPayload.bitcoinAddress, uiPayload.paymentPublicKey, undefined) | ||
const tx = new btc.Transaction({ allowUnknowOutput: true, allowUnknownInputs:true, allowUnknownOutputs:true }); | ||
@@ -41,0 +58,0 @@ addInputs(network, uiPayload.amountSats, revealPayment, tx, false, addressInfo.utxos, uiPayload.paymentPublicKey); |
@@ -6,3 +6,3 @@ import { beforeAll, beforeEach, expect, describe, it } from 'vitest' | ||
buildWithdrawalPayload, parseWithdrawalPayload, | ||
getStacksSimpleHashOfDataToSign, getStacksAddressFromSignature | ||
getStacksSimpleHashOfDataToSign, getStacksAddressFromSignature, PayloadType, parsePayloadFromTransaction, getDataToSign | ||
} from '../src/index'; | ||
@@ -16,2 +16,4 @@ import { sbtcWallets } from '../src/index'; | ||
import * as secp from '@noble/secp256k1'; | ||
import { dust } from '../src/withdraw_utils'; | ||
import { getStacksAddressFromPubkey } from '../src/payload_utils'; | ||
@@ -60,29 +62,31 @@ describe('bitcoin rpc suite - requires bitcoin core running on testnet', () => { | ||
}) | ||
it.concurrent('Check parsing and building withdrawal payload 1', async () => { | ||
const sig = { | ||
publicKey: "032dea00ee2172e11fc18fc3c3ab2712038bf95d7b89330d0195624cc20764e414", | ||
signature: "00b9710b4fda0bcf7a066d49f29ed76032c28862e5c496c5c9803501baa6130eb915e992eef765daaebf06acba5efa49ae8e0a438c5f22b03088c9d94dd061ca30" | ||
} | ||
const getDataToSign = '3600000000000003200014764ad6983a6455cca54cd6a4f7b0da71ba6a0bab'; | ||
const message = '3600000000000003200014764ad6983a6455cca54cd6a4f7b0da71ba6a0bab' | ||
const messageHash = 'b37a0c9bf56598e9d39da2eaf6762c99fd403c61605148a34c505c62271880cc' | ||
getStacksAddressFromPubkey(hex.decode(sig.publicKey)) | ||
const fromAddress = 'tb1qwe9ddxp6v32uef2v66j00vx6wxax5zat223tms' | ||
const stacksAddress = 'ST1NXBK3K5YYMD6FD41MVNP3JS1GABZ8TRVX023PT'; | ||
const amount = 800; | ||
const payload = buildWithdrawalPayload(btc.TEST_NETWORK, amount, hex.decode(sig.signature), false); | ||
//assert(hex.encode(payload) === data); | ||
//const tx = new btc.Transaction({ allowUnknowOutput: true, allowUnknownInputs:true, allowUnknownOutputs:true }); | ||
//tx.addOutputAddress(fromAddress, BigInt(dust), btc.TEST_NETWORK); | ||
/** | ||
*/ | ||
it.concurrent('Check parsing and building withdrawal payload 1', async () => { | ||
const fromAddress = 'tb1qp8r7ln235zx6nd8rsdzkgkrxc238p6eecys2m9' | ||
const stacksAddress = 'ST1R1061ZT6KPJXQ7PAXPFB6ZAZ6ZWW28G8HXK9G5'; | ||
const amount = 942; | ||
//const amountBuf = '00000000000003ae' // 8 bytes | ||
//const messageHash = '00000000000003ae001409c7efcd51a08da9b4e38345645866c2a270eb39' | ||
//const publicKey = "02e30e89dc85db23273fed237c21d4ca495de4fbffbdf8a90d90e902847fb411c7" | ||
let signature = "885b122df0a9a4abb9bc7911dc6d7af5b36a54063fa32476fbfe5ba0a0d039803bb6de6bd3058c4c494d3a6f1c925afd55dc2daa5672d164816457ab8c0ef6e600" | ||
//Sats (be, buf=1): 942 amountToBigUint64:00000000000003ae bigUint64ToAmount:942 | ||
//data = concat(magicBuf, opCodeBuf, amountBuf, signature) | ||
const data = '54323e00000000000003ae885b122df0a9a4abb9bc7911dc6d7af5b36a54063fa32476fbfe5ba0a0d039803bb6de6bd3058c4c494d3a6f1c925afd55dc2daa5672d164816457ab8c0ef6e600' | ||
// 00000000000003ae | ||
//let signature = await secp.signAsync(dataToSignHash, privKey); // sync methods below | ||
//signature = signature.addRecoveryBit(1); | ||
//assert(secp.verify(signature, dataToSignHash, pubKey)); | ||
//const payload = buildWithdrawalPayload(btc.TEST_NETWORK, 5000, signature.toCompactRawBytes(), false); | ||
const payload = buildWithdrawalPayload(btc.TEST_NETWORK, amount, hex.decode(signature), false); | ||
assert(hex.encode(payload) === data); | ||
const parsedPayload = parseWithdrawalPayload('testnet', payload, fromAddress, 0); | ||
const parsedPayload = parseWithdrawalPayload('testnet', payload, fromAddress); | ||
//console.log('parsedPayload1: ', parsedPayload); | ||
assert(parsedPayload.amountSats === amount); | ||
assert(parsedPayload.opcode === '3E'); | ||
assert(parsedPayload.signature === signature); | ||
assert(parsedPayload.stacksAddress === stacksAddress); | ||
assert(parsedPayload.signature === sig.signature); | ||
expect(parsedPayload.stacksAddress).equals(stacksAddress); | ||
}) | ||
@@ -94,55 +98,32 @@ | ||
const amount = 942; | ||
const data = '54323e00000000000003ae885b122df0a9a4abb9bc7911dc6d7af5b36a54063fa32476fbfe5ba0a0d039803bb6de6bd3058c4c494d3a6f1c925afd55dc2daa5672d164816457ab8c0ef6e600' | ||
let signature = '885b122df0a9a4abb9bc7911dc6d7af5b36a54063fa32476fbfe5ba0a0d039803bb6de6bd3058c4c494d3a6f1c925afd55dc2daa5672d164816457ab8c0ef6e600' | ||
const payload = buildWithdrawalPayload(btc.TEST_NETWORK, amount, hex.decode(signature), false); | ||
const parsedPayload = parseWithdrawalPayload('testnet', payload, fromAddress, 0); | ||
//console.log('parsedPayload: ', parsedPayload); | ||
expect(data).equals(hex.encode(payload)); | ||
assert(parsedPayload.amountSats === amount); | ||
assert(parsedPayload.opcode === '3E'); | ||
assert(parsedPayload.stacksAddress === stacksAddress); | ||
assert(parsedPayload.signature === signature); | ||
}) | ||
const sig = { | ||
publicKey: "02e30e89dc85db23273fed237c21d4ca495de4fbffbdf8a90d90e902847fb411c7", | ||
signature: "00251c10f7e9a650409416fd70a4c9f3467723f3bdbcc6a534c1d11776c6da76df57dfddfb524c01776af0443da6fd7be5e189ec4d42290ee80db2a1e7f08dda5e" | ||
} | ||
const getDataToSign = '360000000000000258001409c7efcd51a08da9b4e38345645866c2a270eb39'; | ||
const message = '3600000000000003200014764ad6983a6455cca54cd6a4f7b0da71ba6a0bab' | ||
const messageHash = 'b37a0c9bf56598e9d39da2eaf6762c99fd403c61605148a34c505c62271880cc' | ||
it.concurrent('Check parsing and building withdrawal payload 3', async () => { | ||
const fromAddress = 'tb1qp8r7ln235zx6nd8rsdzkgkrxc238p6eecys2m9' | ||
const stacksAddress = 'ST1R1061ZT6KPJXQ7PAXPFB6ZAZ6ZWW28G8HXK9G5'; | ||
const amount = 242; | ||
const data = '54323e00000000000000f221a7ac825846d024fe29d0db9d9b48b0d520d01398dc4edf0aab15f9b38da27718ddce8a5c6f8bf730858d9619455a68c03338d729b1f623aa1ddb84ee383e6a00' | ||
let signature = '21a7ac825846d024fe29d0db9d9b48b0d520d01398dc4edf0aab15f9b38da27718ddce8a5c6f8bf730858d9619455a68c03338d729b1f623aa1ddb84ee383e6a00' | ||
const payload = buildWithdrawalPayload(btc.TEST_NETWORK, amount, hex.decode(signature), false); | ||
//console.log('payload: ', hex.encode(payload)); | ||
const parsedPayload = parseWithdrawalPayload('testnet', hex.decode(data), fromAddress, 0); | ||
//console.log('parsedPayload: ', parsedPayload); | ||
//console.log('data : ', data); | ||
expect(data).equals(hex.encode(payload)); | ||
const payload = buildWithdrawalPayload(btc.TEST_NETWORK, amount, hex.decode(sig.signature), false); | ||
const parsedPayload = parseWithdrawalPayload('testnet', payload, fromAddress); | ||
//console.log('parsedPayload1: ', parsedPayload); | ||
assert(parsedPayload.amountSats === amount); | ||
assert(parsedPayload.opcode === '3E'); | ||
assert(parsedPayload.stacksAddress === stacksAddress); | ||
assert(parsedPayload.signature === signature); | ||
assert(parsedPayload.signature === sig.signature); | ||
expect(parsedPayload.stacksAddress).equals(stacksAddress); | ||
}) | ||
it.concurrent('Check parsing and building withdrawal payload 4', async () => { | ||
const fromAddress = 'mu5o1rDdfP6g8NKa1RweQDo1zQT58KWjdR' | ||
const stacksAddress = 'ST2ACZ7DAH6EH20V36ES9SJEERBX7VWGWV0YB91PG'; | ||
const amount = 100; | ||
const msgHash = 'ccfa2c7c2a3a4d3928729119d27e4959b77772e457f6d256119ee2211504d1ad' | ||
expect(msgHash).equals(getStacksSimpleHashOfDataToSign('testnet', amount, fromAddress)) | ||
const data = '54323e0000000000000064084a912d26cb8f26652efc53d717a6b6dbdb64042cfbaa06e20b60fef67d144f36643bbba7ed178255497a058774e39fe39493f444f5ca3428d821356a6bfcf501' | ||
let signature = '084a912d26cb8f26652efc53d717a6b6dbdb64042cfbaa06e20b60fef67d144f36643bbba7ed178255497a058774e39fe39493f444f5ca3428d821356a6bfcf501' | ||
const payload = buildWithdrawalPayload(btc.TEST_NETWORK, amount, hex.decode(signature), false); | ||
//console.log('payload: ', hex.encode(payload)); | ||
const parsedPayload = parseWithdrawalPayload('testnet', hex.decode(data), fromAddress, 1); | ||
//console.log('parsedPayload: ', parsedPayload); | ||
//console.log('data : ', data); | ||
expect(data).equals(hex.encode(payload)); | ||
assert(parsedPayload.amountSats === amount); | ||
assert(parsedPayload.opcode === '3E'); | ||
assert(parsedPayload.stacksAddress === stacksAddress); | ||
assert(parsedPayload.signature === signature); | ||
it.concurrent('Parse deposit op_return', async () => { | ||
const txHex = '02000000000101b45477dbbb0529da2113432a3a4956de86225db8cbe7d5542e7789cd6a440f6c0100000000ffffffff0300000000000000004f6a4c4c54323e0000000000000315019d9f202861ef9e2d8ec332aac3f60d922ba7d1a98adf46f9416756e6f750639f4a949af7ff0c7b30dc24c0db2bdd7ea70cf3e9096108eb4023b2eca79d35a494f40100000000000016001409c7efcd51a08da9b4e38345645866c2a270eb39d14305000000000016001409c7efcd51a08da9b4e38345645866c2a270eb3902483045022100de9e244dd9bd6f307e979547e088736f54fde25d250e435fe867ddf4948f4d0202207762316984993ef5a8cefad1723eee8f07200437b87f3c141a39c3b150cffd27012103665ca3afcd61141e97aa9706d180514e28ef8fa29e0425e82a78e5e3b25f2b3600000000'; | ||
const payload:PayloadType = parsePayloadFromTransaction('testnet', txHex); | ||
console.log('Parse deposit op_return:', payload) | ||
expect(payload.stacksAddress).equals('ST1R1061ZT6KPJXQ7PAXPFB6ZAZ6ZWW28G8HXK9G5') | ||
expect(payload.amountSats).equals(100) | ||
expect(payload.opcode).equals('3C') | ||
expect(payload.sbtcWallet).equals('tb1p68eyfa7nprcegz4xdj5q9msjy69xgshzckvy64cmwegfzu77v2wslah8ww') | ||
expect(payload.prinType).equals(0) | ||
}) | ||
}) | ||
204872
40
4870
169