diff --git a/package-lock.json b/package-lock.json index b8b3f37..3d9a863 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "flowbite-svelte-icons": "^0.4.4", "micro-packed": "^0.3.2", "sats-connect": "^1.1.1", - "sbtc-bridge-lib": "^1.1.24", + "sbtc-bridge-lib": "^1.1.25", "sockjs": "^0.3.24", "svelte-local-storage-store": "^0.5.0", "svelte-qrcode": "^1.0.0", @@ -3831,9 +3831,9 @@ } }, "node_modules/sbtc-bridge-lib": { - "version": "1.1.24", - "resolved": "https://registry.npmjs.org/sbtc-bridge-lib/-/sbtc-bridge-lib-1.1.24.tgz", - "integrity": "sha512-FkhGKBa1OQ71DMUE8FbPBnXRJXk+jQ3/+fdJ2qH3o4nzvIIYpvL/tRkl+K5+3JdEq721+zYH2x2/USu1bA1gCw==", + "version": "1.1.25", + "resolved": "https://registry.npmjs.org/sbtc-bridge-lib/-/sbtc-bridge-lib-1.1.25.tgz", + "integrity": "sha512-oeMYH7N0/8FOA0bAiuH2b6yexBqJJgkLJmkT/FO+M8DFF1a2vemX60uy43unaVSg78etSZthyEJEuocDPbMzEA==", "dependencies": { "@noble/secp256k1": "^2.0.0", "@scure/base": "^1.1.1", diff --git a/package.json b/package.json index 5540b35..b06b873 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "flowbite-svelte-icons": "^0.4.4", "micro-packed": "^0.3.2", "sats-connect": "^1.1.1", - "sbtc-bridge-lib": "^1.1.24", + "sbtc-bridge-lib": "^1.1.25", "sockjs": "^0.3.24", "svelte-local-storage-store": "^0.5.0", "svelte-qrcode": "^1.0.0", diff --git a/src/lib/components/admin/DecodeSbtc.svelte b/src/lib/components/admin/DecodeSbtc.svelte index 9a2bb6b..a67f6f4 100644 --- a/src/lib/components/admin/DecodeSbtc.svelte +++ b/src/lib/components/admin/DecodeSbtc.svelte @@ -3,6 +3,8 @@ import { onMount } from 'svelte'; //import { parsePayloadFromTransaction } from 'sbtc-bridge-lib'; import { CONFIG } from '$lib/config'; import { parsePayloadFromTransaction } from 'sbtc-bridge-lib'; + import { mintToMerkle } from '$lib/sbtc_admin'; + import Button from "../shared/Button.svelte"; export let tx:any; let res:any; diff --git a/src/lib/components/admin/TransactionAnalysis.svelte b/src/lib/components/admin/TransactionAnalysis.svelte index 18660f8..5d0d591 100644 --- a/src/lib/components/admin/TransactionAnalysis.svelte +++ b/src/lib/components/admin/TransactionAnalysis.svelte @@ -82,7 +82,7 @@ import VerifyTransactions from './VerifyTransactions.svelte';
{#if tx} {#if feature === 'sbtcDecode'} - + {:else if block} {/if} diff --git a/src/lib/components/admin/VerifyTransactions.svelte b/src/lib/components/admin/VerifyTransactions.svelte index c629073..f17080d 100644 --- a/src/lib/components/admin/VerifyTransactions.svelte +++ b/src/lib/components/admin/VerifyTransactions.svelte @@ -7,7 +7,7 @@ import { onMount } from 'svelte'; import { sha256 } from '@noble/hashes/sha256'; import { explorerAddressUrl } from '$lib/utils'; import { sbtcConfig } from '$stores/stores' -import { bitcoinToSats, generateMerkleRoot, generateMerkleTree, getParametersForProof, type TxMinedParameters } from 'sbtc-bridge-lib'; +import { bitcoinToSats, generateMerkleRoot, generateMerkleTree, getParametersForProof, parsePayloadFromTransaction, type TxMinedParameters } from 'sbtc-bridge-lib'; import { CONFIG } from '$lib/config'; import { loggedIn } from '$lib/stacks_connect'; /** @@ -172,17 +172,19 @@ const verifyMerkleProof = async () => { console.log(answer) } -const mintTo = async () => { - functionName = 'verify-merkle-proof' +const mintTo = async () => { + const data = parsePayloadFromTransaction(CONFIG.VITE_NETWORK, tx.hex) + let prin = data.stacksAddress; + if (typeof (data.lengthOfCname) === 'number' && data.lengthOfCname > 0) prin += '.' + data.cname contractParameters = { amount: tx.vout[1].amount, txid: hex.encode(hex.decode(tx.txid)), - stxAddress: stxAddress, + stxAddress: prin, proofs: (proofString) ? proofString.split(' ').join('
') : parameters.proofElements.map(({ hash }) => hash).join('
'), 'tx-index': parameters.txIndex, } - const res = await romeoMintTo($sbtcConfig.sbtcContractData.contractId, amount, stxAddress!, tx.txid, parameters.height, getProofsAsCV(), parameters.txIndex, parameters.headerHex) + const res = await romeoMintTo($sbtcConfig.sbtcContractData.contractId, amount, prin!, tx.txid, parameters.height, getProofsAsCV(), parameters.txIndex, parameters.headerHex) console.log(res) } @@ -289,7 +291,6 @@ onMount(async () => {
-
{/if} {#if showTree} diff --git a/src/lib/components/dashboard/dr/SignTransaction.svelte b/src/lib/components/dashboard/dr/SignTransaction.svelte index a99a4a6..323535e 100644 --- a/src/lib/components/dashboard/dr/SignTransaction.svelte +++ b/src/lib/components/dashboard/dr/SignTransaction.svelte @@ -7,7 +7,7 @@ import { sbtcConfig } from '$stores/stores'; import { explorerBtcTxUrl } from "$lib/utils"; import { saveBridgeTransaction } from '$lib/bridge_api'; import type { BridgeTransactionType } from 'sbtc-bridge-lib' -import { buildDepositTransaction, buildDepositTransactionOpDrop } from 'sbtc-bridge-lib' +import { buildDepositPayload, buildDepositTransaction, buildDepositTransactionOpDrop, parseDepositPayload } from 'sbtc-bridge-lib' import { appDetails, getStacksNetwork, isLeather } from "$lib/stacks_connect"; import Invoice from '../shared/Invoice.svelte'; import { CONFIG } from '$lib/config'; @@ -16,6 +16,7 @@ import { BitcoinNetworkType, signTransaction, type SignTransactionOptions } from import { broadcastTransaction } from '$lib/sbtc'; import type { Transaction, TransactionOutput, TransactionInput } from '@scure/btc-signer'; import { Tooltip } from 'flowbite-svelte'; + import { buildDepositPayloadInternal } from '$lib/stacks_connect_bug'; export let peginRequest:BridgeTransactionType; export let addressInfo:any; @@ -146,6 +147,15 @@ onMount(async () => { transaction = buildDepositTransactionOpDrop(CONFIG.VITE_NETWORK, $sbtcConfig.payloadDepositData, $sbtcConfig.btcFeeRates, addressInfo.utxos, peginRequest.commitTxScript!.address!); } else { transaction = buildDepositTransaction(CONFIG.VITE_NETWORK, $sbtcConfig.sbtcContractData.sbtcWalletPublicKey, $sbtcConfig.payloadDepositData, $sbtcConfig.btcFeeRates, addressInfo.utxos) + /** + */ + const data1 = buildDepositPayloadInternal(0, $sbtcConfig.payloadDepositData.principal, false) + const dout1 = parseDepositPayload(hex.decode(data1)) + const data = buildDepositPayload(CONFIG.VITE_NETWORK, $sbtcConfig.payloadDepositData.principal); + const dout = parseDepositPayload(hex.decode(data)) + console.log(data1) + console.log(dout) + console.log(dout1) } if (transaction.inputsLength === 0) { errorReason = '

Unable to create / sign transaction

You can change the bitcoin address on the previous screen to your Bitcoin Core or Electrum wallet and then copy paste the PSBT before signing and broadcasting the transaction.

' diff --git a/src/lib/config.ts b/src/lib/config.ts index bda07d0..3aa960f 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -4,7 +4,7 @@ const SHARED_DEVENV_CONFIG = { VITE_PUBLIC_APP_VERSION: '1.0.0', VITE_NETWORK: 'devnet', VITE_SBTC_COORDINATOR: 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM', - VITE_BRIDGE_WS: 'ws://localhost:3010', + VITE_BRIDGE_WS: 'ws://45.79.130.153:3999', VITE_BRIDGE_API: 'http://45.79.130.153:3010/bridge-api/v1', VITE_STACKS_API: 'http://45.79.130.153:3999', VITE_STACKS_EXPLORER: 'http://45.79.130.153:3020', @@ -18,7 +18,7 @@ const SHARED_DEVENV_LOCAL_CONFIG = { VITE_PUBLIC_APP_VERSION: '1.0.0', VITE_NETWORK: 'devnet', VITE_SBTC_COORDINATOR: 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM', - VITE_BRIDGE_WS: 'ws://localhost:3010', + VITE_BRIDGE_WS: 'ws://45.79.130.153:3999', VITE_BRIDGE_API: 'http://45.79.130.153:3010/bridge-api/v1', VITE_STACKS_API: 'http://45.79.130.153:3999', VITE_STACKS_EXPLORER: 'http://45.79.130.153:3020', diff --git a/src/lib/sbtc_admin.ts b/src/lib/sbtc_admin.ts index 3d21356..a4a6a74 100644 --- a/src/lib/sbtc_admin.ts +++ b/src/lib/sbtc_admin.ts @@ -2,7 +2,7 @@ * sbtc - interact with Stacks Blockchain to read sbtc contract info */ import { CONFIG } from '$lib/config'; -import { PostConditionMode, uintCV, stringAsciiCV, bufferCVFromString, bufferCV, cvToJSON, deserializeCV, type ListCV } from '@stacks/transactions'; +import { PostConditionMode, uintCV, stringAsciiCV, bufferCVFromString, bufferCV, cvToJSON, deserializeCV, type ListCV, contractPrincipalCV } from '@stacks/transactions'; import { tupleCV } from '@stacks/transactions/dist/esm/clarity/index.js'; import { principalCV } from '@stacks/transactions/dist/esm/clarity/types/principalCV.js'; import { openContractCall } from '@stacks/connect'; @@ -29,7 +29,10 @@ export function isCoordinator(address:string) { export async function romeoMintTo(contractId:string, amount:number, stxAddress: string, btcTxid: string, height: number, merkleProofs: ListCV, txIndex:number, headerHex: string) { //data {addr: principal, key: (buff 33)} - const stxAddressCV = principalCV(stxAddress); + let stxAddressCV = principalCV(stxAddress); + if (stxAddress.indexOf('.') > -1) { + stxAddressCV = contractPrincipalCV(stxAddress.split('.')[0], stxAddress.split('.')[1]); + } const functionArgs = [uintCV(amount), stxAddressCV, bufferCV(hex.decode(btcTxid)), uintCV(height), merkleProofs, uintCV(txIndex), bufferCV(hex.decode(headerHex))] await openContractCall({ network: getStacksNetwork(), @@ -73,6 +76,32 @@ export async function mintTo(contractId:string, amount:number, stxAddress: strin }); } +export async function mintToMerkle(amount:number, stxAddress: string, btcTxid: string) { + //data {addr: principal, key: (buff 33)} + const contractId = CONFIG.VITE_SBTC_COORDINATOR + '.asset' + + const btcTxidCV = bufferCV(hex.decode(btcTxid)) + const stxAddressCV = principalCV(stxAddress); + const functionArgs = [uintCV(amount), stxAddressCV, btcTxidCV] + + await openContractCall({ + network: getStacksNetwork(), + postConditions: [], + postConditionMode: PostConditionMode.Deny, + contractAddress: contractId.split('.')[0], + contractName: contractId.split('.')[1], + functionName: 'mint', + functionArgs: functionArgs, + onFinish: (data: any) => { + console.log('TX Data: ', data); + return data; + }, + onCancel: () => { + console.log('popup closed!'); + } + }); +} + export async function burnFrom(contractId:string, amount:number, stxAddress: string, btcTxid: string) { //data {addr: principal, key: (buff 33)} const btcAddressCV = stringAsciiCV(btcTxid); diff --git a/src/lib/stacks_connect_bug.ts b/src/lib/stacks_connect_bug.ts index 1db0a55..68ecbb2 100644 --- a/src/lib/stacks_connect_bug.ts +++ b/src/lib/stacks_connect_bug.ts @@ -7,9 +7,56 @@ import { signMessageHashRsv, } from '@stacks/transactions'; import { sha256 } from '@noble/hashes/sha256'; -import { MAGIC_BYTES_MAINNET, MAGIC_BYTES_TESTNET, getAddressFromOutScript, parseDepositPayload, parseWithdrawPayload, type PayloadType } from 'sbtc-bridge-lib'; -import * as btc from '@scure/btc-signer'; +import { MAGIC_BYTES_TESTNET, PEGIN_OPCODE, amountToBigUint64 } from 'sbtc-bridge-lib'; import { hex } from '@scure/base'; +import { c32addressDecode } from 'c32check'; +import * as P from 'micro-packed'; +const concat = P.concatBytes; + +export function buildDepositPayloadInternal(amountSats:number, address:string, opDrop:boolean):string { + const magicBuf = hex.decode(MAGIC_BYTES_TESTNET) + const opCodeBuf = hex.decode(PEGIN_OPCODE); + const addr = c32addressDecode(address.split('.')[0]) + //const addr0Buf = hex.encode(amountToUint8(addr[0], 1)); + const addr0Buf = (hex.decode(addr[0].toString(16))); + const addr1Buf = hex.decode(addr[1]); + + const cnameLength = new Uint8Array(1); + //const memoLength = new Uint8Array(1); + const principalType = (address.indexOf('.') > -1) ? hex.decode('06') : hex.decode('05'); + let buf1 = concat(opCodeBuf, principalType, addr0Buf, addr1Buf); + if (address.indexOf('.') > -1) { + const cnameBuf = new TextEncoder().encode(address.split('.')[1]); + const cnameBufHex = hex.encode(cnameBuf) + let cnameLen:any; + try { + cnameLen = hex.decode(cnameBuf.length.toString(8)) + } catch (err) { + cnameLen = cnameLength.fill(cnameBufHex.length); + } + buf1 = concat(buf1, cnameLen, cnameBuf); + } else { + cnameLength.fill(0); + buf1 = concat(buf1, cnameLength); + } + /** + if (memo) { + const memoBuf = new TextEncoder().encode(memo); + const memoLength = hex.decode(memoBuf.length.toString(8)); + buf1 = concat(buf1, memoLength, memoBuf); + } else { + memoLength.fill(0); + buf1 = concat(buf1, memoLength); + } + */ + if (opDrop) { + const feeBuf = amountToBigUint64(amountSats, 8) + buf1 = concat(buf1, feeBuf) + } + + if (!opDrop) return hex.encode(concat(magicBuf, buf1)) + return hex.encode(buf1); +} export const keyChain = { "mnemonic": "foster raise devote wear great volcano spring chapter among violin bleak syrup rent sphere coyote client govern spirit good risk cruise twice trick jealous",