diff --git a/apps/backend/migrations/20241106142510_multichain_recreate.js b/apps/backend/migrations/20241106142510_multichain_recreate.js new file mode 100644 index 00000000..8a52a840 --- /dev/null +++ b/apps/backend/migrations/20241106142510_multichain_recreate.js @@ -0,0 +1,7 @@ +import { upSQL } from 'knex-migrate-sql-file'; + +export async function up(knex) { + await upSQL(knex); +} + +export function down() {} diff --git a/apps/backend/migrations/20241106142510_multichain_recreate.up.sql b/apps/backend/migrations/20241106142510_multichain_recreate.up.sql new file mode 100644 index 00000000..91dfb4b7 --- /dev/null +++ b/apps/backend/migrations/20241106142510_multichain_recreate.up.sql @@ -0,0 +1,51 @@ +DROP TABLE multichain_accounts; + +DROP TABLE multichain_transactions; + +CREATE TABLE multichain_accounts ( + account_id TEXT NOT NULL, + chain TEXT NOT NULL, + path TEXT NOT NULL, + derived_address TEXT NOT NULL, + public_key TEXT NOT NULL, + block_height NUMERIC(20, 0) NOT NULL, + block_timestamp BIGINT NOT NULL, + PRIMARY KEY (account_id, chain, path) +); + +CREATE TABLE multichain_transactions ( + id BIGINT GENERATED ALWAYS AS IDENTITY, + receipt_id TEXT NOT NULL, + account_id TEXT NOT NULL, + derived_address TEXT NOT NULL, + public_key TEXT NOT NULL, + chain TEXT NOT NULL, + path TEXT NOT NULL, + derived_transaction TEXT, + block_height NUMERIC(20, 0) NOT NULL, + block_timestamp BIGINT NOT NULL, + PRIMARY KEY (id), + UNIQUE (receipt_id) +); + +CREATE INDEX ma_account_id_idx ON multichain_accounts USING btree (account_id); + +CREATE INDEX ma_derived_address_idx ON multichain_accounts USING btree (derived_address); + +CREATE INDEX ma_block_height_idx ON multichain_accounts USING btree (block_height DESC); + +CREATE INDEX ma_block_timestamp_idx ON multichain_accounts USING btree (block_timestamp DESC); + +CREATE INDEX mt_receipt_id_idx ON multichain_transactions USING btree (receipt_id); + +CREATE INDEX mt_account_id_idx ON multichain_transactions USING btree (account_id); + +CREATE INDEX mt_derived_address_idx ON multichain_transactions USING btree (derived_address); + +CREATE INDEX mt_derived_transaction_idx ON multichain_transactions USING btree (derived_transaction) +WHERE + derived_transaction IS NOT NULL; + +CREATE INDEX mt_block_height_idx ON multichain_transactions USING btree (block_height DESC); + +CREATE INDEX mt_block_timestamp_idx ON multichain_transactions USING btree (block_timestamp DESC); diff --git a/apps/indexer-multichain/package.json b/apps/indexer-multichain/package.json index aff3141f..5c57d3a3 100644 --- a/apps/indexer-multichain/package.json +++ b/apps/indexer-multichain/package.json @@ -16,8 +16,11 @@ "lint:check": "tsc --noEmit && eslint ./" }, "dependencies": { + "@cosmjs/crypto": "0.32.4", + "@cosmjs/encoding": "0.32.4", "@sentry/node": "7.74.1", - "bs58check": "4.0.0", + "bech32": "2.0.0", + "bitcoinjs-lib": "7.0.0-rc.0", "elliptic": "6.6.0", "envalid": "8.0.0", "js-sha3": "0.9.3", diff --git a/apps/indexer-multichain/src/libs/bitcoin.ts b/apps/indexer-multichain/src/libs/bitcoin.ts index f415b6ba..8b73f4fc 100644 --- a/apps/indexer-multichain/src/libs/bitcoin.ts +++ b/apps/indexer-multichain/src/libs/bitcoin.ts @@ -1,59 +1,34 @@ -import crypto from 'node:crypto'; - -import bs58check from 'bs58check'; -import hash from 'hash.js'; +import * as bitcoin from 'bitcoinjs-lib'; import { Network } from 'nb-types'; import config from '#config'; -import { - deriveChildPublicKey, - najPublicKeyStrToUncompressedHexPoint, -} from '#libs/kdf'; +import { generateCompressedPublicKey } from '#libs/kdf'; -const network = config.network === Network.MAINNET ? 'bitcoin' : 'testnet'; +const network = + config.network === Network.MAINNET + ? bitcoin.networks.bitcoin + : bitcoin.networks.testnet; -const deriveAddress = async (accountId: string, derivation_path: string) => { - const publicKey = await deriveChildPublicKey( - najPublicKeyStrToUncompressedHexPoint(), +const deriveAddress = async (accountId: string, derivationPath: string) => { + const derivedKey = await generateCompressedPublicKey( accountId, - derivation_path, - ); - const address = await uncompressedHexPointToBtcAddress(publicKey, network); - - return { address, publicKey }; -}; - -const uncompressedHexPointToBtcAddress = async ( - publicKeyHex: string, - network: string, -) => { - // Step 1: SHA-256 hashing of the public key - const publicKeyBytes = Uint8Array.from(Buffer.from(publicKeyHex, 'hex')); - - const sha256HashOutput = await crypto.subtle.digest( - 'SHA-256', - publicKeyBytes, + derivationPath, ); - // Step 2: RIPEMD-160 hashing on the result of SHA-256 - const ripemd160 = hash - .ripemd160() - .update(Buffer.from(sha256HashOutput)) - .digest(); + const publicKeyBuffer = Buffer.from(derivedKey, 'hex'); - // Step 3: Adding network byte (0x00 for Bitcoin Mainnet) - const network_byte = network === 'bitcoin' ? 0x00 : 0x6f; - const networkByte = Buffer.from([network_byte]); - const networkByteAndRipemd160 = Buffer.concat([ - networkByte, - Buffer.from(ripemd160), - ]); + // Use P2WPKH (Bech32) address type + const { address } = bitcoin.payments.p2wpkh({ + network, + pubkey: publicKeyBuffer, + }); - // Step 4: Base58Check encoding - const address = bs58check.encode(networkByteAndRipemd160); + if (!address) { + throw new Error('Failed to generate Bitcoin address'); + } - return address; + return { address, publicKey: derivedKey }; }; export default deriveAddress; diff --git a/apps/indexer-multichain/src/libs/cosmos.ts b/apps/indexer-multichain/src/libs/cosmos.ts new file mode 100644 index 00000000..02a985aa --- /dev/null +++ b/apps/indexer-multichain/src/libs/cosmos.ts @@ -0,0 +1,33 @@ +import { ripemd160, Secp256k1, sha256 } from '@cosmjs/crypto'; +import { fromHex } from '@cosmjs/encoding'; +import { bech32 } from 'bech32'; + +import { generateCompressedPublicKey } from './kdf.js'; + +// implementation is pending becuase prefix is required for cosmos +const deriveAddress = async ( + accountId: string, + derivationPath: string, + prefix: string, +) => { + const derivedKeyHex = await generateCompressedPublicKey( + accountId, + derivationPath, + ); + + const publicKey = fromHex(derivedKeyHex); + const address = pubkeyToAddress(publicKey, prefix); + + return { address, publicKey: derivedKeyHex }; +}; + +const pubkeyToAddress = (pubkey: Uint8Array, prefix: string) => { + const pubkeyRaw = + pubkey.length === 33 ? pubkey : Secp256k1.compressPubkey(pubkey); + const sha256Hash = sha256(pubkeyRaw); + const ripemd160Hash = ripemd160(sha256Hash); + + return bech32.encode(prefix, bech32.toWords(ripemd160Hash)); +}; + +export default deriveAddress; diff --git a/apps/indexer-multichain/src/libs/ethereum.ts b/apps/indexer-multichain/src/libs/ethereum.ts index dfff7012..8f383b47 100644 --- a/apps/indexer-multichain/src/libs/ethereum.ts +++ b/apps/indexer-multichain/src/libs/ethereum.ts @@ -2,14 +2,14 @@ import { keccak256 } from 'viem'; import { deriveChildPublicKey, - najPublicKeyStrToUncompressedHexPoint, + signerUncompressedPublicKeyHex, } from '#libs/kdf'; -const deriveAddress = async (accountId: string, derivation_path: string) => { +const deriveAddress = async (accountId: string, derivationPath: string) => { const publicKey = await deriveChildPublicKey( - najPublicKeyStrToUncompressedHexPoint(), + signerUncompressedPublicKeyHex, accountId, - derivation_path, + derivationPath, ); const address = uncompressedHexPointToEvmAddress(publicKey); diff --git a/apps/indexer-multichain/src/libs/kdf.ts b/apps/indexer-multichain/src/libs/kdf.ts index 87ed1d37..c1c14cdf 100644 --- a/apps/indexer-multichain/src/libs/kdf.ts +++ b/apps/indexer-multichain/src/libs/kdf.ts @@ -8,6 +8,7 @@ import config from '#config'; const { ec: EC } = elliptic; const { sha3_256 } = jsSha3; +const ec = new EC('secp256k1'); export const signer = config.network === Network.MAINNET @@ -22,11 +23,30 @@ export const signer = 'secp256k1:4NfTiv3UsGahebgTaHyD9vF8KYKMBnfd6kh94mK6xv8fGBiJB8TBtFMP5WWXz6B89Ac1fbpzPwAvoyQebemHFwx3', }; -export const najPublicKeyStrToUncompressedHexPoint = () => { - return ( - '04' + - Buffer.from(base_decode(signer.publicKey.split(':')[1])).toString('hex') +export const signerUncompressedPublicKeyHex = + '04' + + Buffer.from(base_decode(signer.publicKey.split(':')[1])).toString('hex'); + +export const generateCompressedPublicKey = async ( + signerId: string, + path: string, +): Promise => { + const derivedPublicKeyHex = await deriveChildPublicKey( + signerUncompressedPublicKeyHex, + signerId, + path, ); + + const publicKeyBuffer = Buffer.from(derivedPublicKeyHex, 'hex'); + + // Compress the public key + const compressedPublicKey = ec + .keyFromPublic(publicKeyBuffer) + .getPublic() + .encodeCompressed(); + + // Return the compressed public key as a hex string + return Buffer.from(compressedPublicKey).toString('hex'); }; export const deriveChildPublicKey = async ( @@ -34,7 +54,6 @@ export const deriveChildPublicKey = async ( signerId: string, path = '', ) => { - const ec = new EC('secp256k1'); const scalarHex = sha3_256( `near-mpc-recovery v0.1.0 epsilon derivation:${signerId},${path}`, ); diff --git a/apps/indexer-multichain/src/services/multichain.ts b/apps/indexer-multichain/src/services/multichain.ts index 86dae94a..e20069e4 100644 --- a/apps/indexer-multichain/src/services/multichain.ts +++ b/apps/indexer-multichain/src/services/multichain.ts @@ -16,9 +16,17 @@ import { Sign } from '#types/types'; type ChainData = { address: null | string; chain: null | string; + parsedPath: null | string; publicKey: null | string; }; +const errorData = { + address: null, + chain: null, + parsedPath: null, + publicKey: null, +}; + export const storeMultichainData = async (message: types.StreamerMessage) => { await Promise.all( message.shards.map(async (shard) => { @@ -98,7 +106,7 @@ export const storeChunkData = async ( retry(async () => { await knex('multichain_accounts') .insert(accounts) - .onConflict(['account_id', 'derived_address']) + .onConflict(['account_id', 'chain', 'path']) .ignore(); }), ); @@ -125,9 +133,12 @@ const getDerivedData = async ( predecessor: string, path: string, ) => { - const { address, chain, publicKey } = await getChainData(predecessor, path); + const { address, chain, parsedPath, publicKey } = await getChainData( + predecessor, + path, + ); - if (address && chain && publicKey) { + if (address && chain && parsedPath && publicKey) { return getTableData( receiptId, blockHeight, @@ -136,11 +147,11 @@ const getDerivedData = async ( address, publicKey, chain, - path, + parsedPath, ); } - logger.warn({ path, predecessor, receiptId }); + logger.warn({ parsedPath, path, predecessor, receiptId }); return { account: null, transaction: null }; }; @@ -149,25 +160,25 @@ const getChainData = async ( predecessor: string, path: string, ): Promise => { - const errorData = { address: null, chain: null, publicKey: null }; + const parsedPath = path.replace(/\\/g, ''); switch (true) { - case path.startsWith('ethereum'): - case path.replace(/\\'/g, "'").startsWith("m/44'/60"): - return getEvmData(predecessor, path); - case path.startsWith('bitcoin'): - case path.replace(/\\'/g, "'").startsWith("m/44'/0"): - return getBtcData(predecessor, path); + case parsedPath.startsWith('ethereum'): + case parsedPath.startsWith("m/44'/60'"): + return getEvmData(predecessor, parsedPath); + case parsedPath.startsWith('bitcoin'): + case parsedPath.startsWith("m/44'/0'"): + return getBtcData(predecessor, parsedPath); default: { - if (path.includes('chain')) { + if (parsedPath.includes('chain')) { try { - const chainData = jsonParse(path.replace(/\\/g, '')); + const chainData = jsonParse(parsedPath); - switch (chainData?.chain) { + switch (+chainData?.chain) { case 60: - return getEvmData(predecessor, path); + return getEvmData(predecessor, JSON.stringify(chainData)); case 0: - return getBtcData(predecessor, path); + return getBtcData(predecessor, JSON.stringify(chainData)); default: return errorData; } @@ -183,29 +194,59 @@ const getChainData = async ( const getEvmData = async ( predecessor: string, - path: string, + parsedPath: string, ): Promise => { try { - const derivedData = await ethereum(predecessor, path); + const address = await knex('multichain_accounts') + .where('account_id', predecessor) + .where('chain', Chains.ETHEREUM) + .where('path', parsedPath) + .first(); + + if (address) { + return { + address: address.derived_address, + chain: address.chain, + parsedPath, + publicKey: address.public_key, + }; + } + + const derivedData = await ethereum(predecessor, parsedPath); - return { chain: Chains.ETHEREUM, ...derivedData }; + return { chain: Chains.ETHEREUM, ...derivedData, parsedPath }; } catch (error) { logger.error(error); - return { address: null, chain: null, publicKey: null }; + return errorData; } }; const getBtcData = async ( predecessor: string, - path: string, + parsedPath: string, ): Promise => { try { - const derivedData = await bitcoin(predecessor, path); + const address = await knex('multichain_accounts') + .where('account_id', predecessor) + .where('chain', Chains.BITCOIN) + .where('path', parsedPath) + .first(); + + if (address) { + return { + address: address.derived_address, + chain: address.chain, + parsedPath, + publicKey: address.public_key, + }; + } + + const derivedData = await bitcoin(predecessor, parsedPath); - return { chain: Chains.BITCOIN, ...derivedData }; + return { chain: Chains.BITCOIN, ...derivedData, parsedPath }; } catch (error) { logger.error(error); - return { address: null, chain: null, publicKey: null }; + return errorData; } }; diff --git a/apps/indexer-multichain/src/types/enum.ts b/apps/indexer-multichain/src/types/enum.ts index 39093279..f171926f 100644 --- a/apps/indexer-multichain/src/types/enum.ts +++ b/apps/indexer-multichain/src/types/enum.ts @@ -5,5 +5,6 @@ export enum DataSource { export enum Chains { BITCOIN = 'BITCOIN', + COSMOS = 'COSMOS', ETHEREUM = 'ETHEREUM', } diff --git a/yarn.lock b/yarn.lock index aed336a8..b871ecbb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2319,6 +2319,40 @@ resolved "https://registry.yarnpkg.com/@corex/deepmerge/-/deepmerge-4.0.43.tgz#9bd42559ebb41cc5a7fb7cfeea5f231c20977dca" integrity sha512-N8uEMrMPL0cu/bdboEWpQYb/0i2K5Qn8eCsxzOmxSggJbbQte7ljMRoXm917AbntqTGOzdTu+vP3KOOzoC70HQ== +"@cosmjs/crypto@0.32.4": + version "0.32.4" + resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.32.4.tgz#5d29633b661eaf092ddb3e7ea6299cfd6f4507a2" + integrity sha512-zicjGU051LF1V9v7bp8p7ovq+VyC91xlaHdsFOTo2oVry3KQikp8L/81RkXmUIT8FxMwdx1T7DmFwVQikcSDIw== + dependencies: + "@cosmjs/encoding" "^0.32.4" + "@cosmjs/math" "^0.32.4" + "@cosmjs/utils" "^0.32.4" + "@noble/hashes" "^1" + bn.js "^5.2.0" + elliptic "^6.5.4" + libsodium-wrappers-sumo "^0.7.11" + +"@cosmjs/encoding@0.32.4", "@cosmjs/encoding@^0.32.4": + version "0.32.4" + resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.32.4.tgz#646e0e809f7f4f1414d8fa991fb0ffe6c633aede" + integrity sha512-tjvaEy6ZGxJchiizzTn7HVRiyTg1i4CObRRaTRPknm5EalE13SV+TCHq38gIDfyUeden4fCuaBVEdBR5+ti7Hw== + dependencies: + base64-js "^1.3.0" + bech32 "^1.1.4" + readonly-date "^1.0.0" + +"@cosmjs/math@^0.32.4": + version "0.32.4" + resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.32.4.tgz#87ac9eadc06696e30a30bdb562a495974bfd0a1a" + integrity sha512-++dqq2TJkoB8zsPVYCvrt88oJWsy1vMOuSOKcdlnXuOA/ASheTJuYy4+oZlTQ3Fr8eALDLGGPhJI02W2HyAQaw== + dependencies: + bn.js "^5.2.0" + +"@cosmjs/utils@^0.32.4": + version "0.32.4" + resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.32.4.tgz#a9a717c9fd7b1984d9cefdd0ef6c6f254060c671" + integrity sha512-D1Yc+Zy8oL/hkUkFUL/bwxvuDBzRGpc4cF7/SkdhxX4iHpSLgdOuTt1mhCh9+kl6NQREy9t7SYZ6xeW5gFe60w== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -5271,7 +5305,7 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== -"@noble/hashes@1.5.0", "@noble/hashes@^1.2.0", "@noble/hashes@^1.4.0", "@noble/hashes@~1.5.0": +"@noble/hashes@1.5.0", "@noble/hashes@^1", "@noble/hashes@^1.2.0", "@noble/hashes@^1.4.0", "@noble/hashes@~1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0" integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA== @@ -10719,7 +10753,7 @@ base-x@^5.0.0: resolved "https://registry.yarnpkg.com/base-x/-/base-x-5.0.0.tgz#6d835ceae379130e1a4cb846a70ac4746f28ea9b" integrity sha512-sMW3VGSX1QWVFA6l8U62MLKz29rRfpTlYdCqLdpLo1/Yd4zZwSbnUaDfciIAowAqvq7YFnWq9hrhdg1KYgc1lQ== -base64-js@1.5.1, base64-js@^1.3.1: +base64-js@1.5.1, base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -10729,11 +10763,16 @@ base64id@2.0.0, base64id@~2.0.0: resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== -bech32@1.1.4: +bech32@1.1.4, bech32@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== +bech32@2.0.0, bech32@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355" + integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg== + big-integer@^1.6.48: version "1.6.52" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" @@ -10763,6 +10802,14 @@ binary-install@^1.0.6: rimraf "^3.0.2" tar "^6.1.11" +bip174@^3.0.0-rc.0: + version "3.0.0-rc.1" + resolved "https://registry.yarnpkg.com/bip174/-/bip174-3.0.0-rc.1.tgz#08c41d5a4cbfa0790075335b64b9a16630fcd73f" + integrity sha512-+8P3BpSairVNF2Nee6Ksdc1etIjWjBOi/MH0MwKtq9YaYp+S2Hk2uvup0e8hCT4IKlS58nXJyyQVmW92zPoD4Q== + dependencies: + uint8array-tools "^0.0.9" + varuint-bitcoin "^2.0.0" + bip39-light@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/bip39-light/-/bip39-light-1.0.7.tgz#06a72f251b89389a136d3f177f29b03342adc5ba" @@ -10781,6 +10828,19 @@ bip39@3.0.2: pbkdf2 "^3.0.9" randombytes "^2.0.1" +bitcoinjs-lib@7.0.0-rc.0: + version "7.0.0-rc.0" + resolved "https://registry.yarnpkg.com/bitcoinjs-lib/-/bitcoinjs-lib-7.0.0-rc.0.tgz#841a7e3a00d4fd719ab7f85f691b2e0455494786" + integrity sha512-7CQgOIbREemKR/NT2uc3uO/fkEy+6CM0sLxboVVY6bv6DbZmPt3gg5Y/hhWgQFeZu5lfTbtVAv32MIxf7lMh4g== + dependencies: + "@noble/hashes" "^1.2.0" + bech32 "^2.0.0" + bip174 "^3.0.0-rc.0" + bs58check "^4.0.0" + uint8array-tools "^0.0.9" + valibot "^0.38.0" + varuint-bitcoin "^2.0.0" + bn.js@4.11.8: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" @@ -11033,7 +11093,7 @@ bs58@^6.0.0: dependencies: base-x "^5.0.0" -bs58check@4.0.0: +bs58check@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-4.0.0.tgz#46cda52a5713b7542dcb78ec2efdf78f5bf1d23c" integrity sha512-FsGDOnFg9aVI9erdriULkd/JjEWONV/lQE5aYziB5PoBsXRind56lh8doIZIc9X4HoxT5x4bLjMWN1/NB8Zp5g== @@ -15465,6 +15525,18 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +libsodium-sumo@^0.7.15: + version "0.7.15" + resolved "https://registry.yarnpkg.com/libsodium-sumo/-/libsodium-sumo-0.7.15.tgz#91c1d863fe3fbce6d6b9db1aadaa622733a1d007" + integrity sha512-5tPmqPmq8T8Nikpm1Nqj0hBHvsLFCXvdhBFV7SGOitQPZAA6jso8XoL0r4L7vmfKXr486fiQInvErHtEvizFMw== + +libsodium-wrappers-sumo@^0.7.11: + version "0.7.15" + resolved "https://registry.yarnpkg.com/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.15.tgz#0ef2a99b4b17e8385aa7e6850593660dbaf5fb40" + integrity sha512-aSWY8wKDZh5TC7rMvEdTHoyppVq/1dTSAeAR7H6pzd6QRT3vQWcT5pGwCotLcpPEOLXX6VvqihSPkpEhYAjANA== + dependencies: + libsodium-sumo "^0.7.15" + lie@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" @@ -19269,6 +19341,11 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +readonly-date@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/readonly-date/-/readonly-date-1.0.0.tgz#5af785464d8c7d7c40b9d738cbde8c646f97dcd9" + integrity sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ== + real-require@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381" @@ -20837,6 +20914,16 @@ ufo@^1.3.0, ufo@^1.3.1, ufo@^1.3.2: resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.4.0.tgz#39845b31be81b4f319ab1d99fd20c56cac528d32" integrity sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ== +uint8array-tools@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/uint8array-tools/-/uint8array-tools-0.0.8.tgz#712bab001f8347bd782f45bc47c76ffff32d1e0b" + integrity sha512-xS6+s8e0Xbx++5/0L+yyexukU7pz//Yg6IHg3BKhXotg1JcYtgxVcUctQ0HxLByiJzpAkNFawz1Nz5Xadzo82g== + +uint8array-tools@^0.0.9: + version "0.0.9" + resolved "https://registry.yarnpkg.com/uint8array-tools/-/uint8array-tools-0.0.9.tgz#e29e6d05f3472273db1b0e370ac1d91e4a0a4e6f" + integrity sha512-9vqDWmoSXOoi+K14zNaf6LBV51Q8MayF0/IiQs3GlygIKUYtog603e6virExkjjFosfJUBI4LhbQK1iq8IG11A== + uint8arrays@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.0.tgz#8186b8eafce68f28bd29bd29d683a311778901e2" @@ -21175,6 +21262,11 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^2.0.0" +valibot@^0.38.0: + version "0.38.0" + resolved "https://registry.yarnpkg.com/valibot/-/valibot-0.38.0.tgz#2d035d2a5bd36e8ea8b48b56d44552ace1a7616f" + integrity sha512-RCJa0fetnzp+h+KN9BdgYOgtsMAG9bfoJ9JSjIhFHobKWVWyzM3jjaeNTdpFK9tQtf3q1sguXeERJ/LcmdFE7w== + valtio@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/valtio/-/valtio-1.10.5.tgz#7852125e3b774b522827d96bd9c76d285c518678" @@ -21199,6 +21291,13 @@ valtio@1.11.2: proxy-compare "2.5.1" use-sync-external-store "1.2.0" +varuint-bitcoin@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/varuint-bitcoin/-/varuint-bitcoin-2.0.0.tgz#59a53845a87ad18c42f184a3d325074465341523" + integrity sha512-6QZbU/rHO2ZQYpWFDALCDSRsXbAs1VOEmXAxtbtjLtKuMJ/FQ8YbhfxlaiKv5nklci0M6lZtlZyxo9Q+qNnyog== + dependencies: + uint8array-tools "^0.0.8" + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"