diff --git a/.env b/.env index 95c3cb8c5bd..316eb96e130 100644 --- a/.env +++ b/.env @@ -157,7 +157,8 @@ VITE_MONAD_NODE_URL=https://rpc.monad.xyz VITE_PLASMA_NODE_URL=https://rpc.plasma.to # VITE_THORCHAIN_NODE_URL=https://api.thorchain.shapeshift.com/lcd VITE_THORCHAIN_NODE_URL=https://thornode.ninerealms.com -VITE_MAYACHAIN_NODE_URL=https://api.mayachain.shapeshift.com/lcd +# VITE_MAYACHAIN_NODE_URL=https://api.mayachain.shapeshift.com/lcd +VITE_MAYACHAIN_NODE_URL=https://mayanode.mayachain.info VITE_SOLANA_NODE_URL=https://api.solana.shapeshift.com/api/v1/jsonrpc VITE_TRON_NODE_URL=https://api.trongrid.io VITE_ALCHEMY_POLYGON_URL=https://polygon-mainnet.g.alchemy.com/v2/anoTMcIc2hbPUxri37h4DeuUwg2p5_xZ @@ -165,7 +166,8 @@ VITE_ALCHEMY_POLYGON_URL=https://polygon-mainnet.g.alchemy.com/v2/anoTMcIc2hbPUx # midgard # VITE_THORCHAIN_MIDGARD_URL=https://api.thorchain.shapeshift.com/midgard/v2 VITE_THORCHAIN_MIDGARD_URL=https://midgard.ninerealms.com/v2 -VITE_MAYACHAIN_MIDGARD_URL=https://api.mayachain.shapeshift.com/midgard/v2 +# VITE_MAYACHAIN_MIDGARD_URL=https://api.mayachain.shapeshift.com/midgard/v2 +VITE_MAYACHAIN_MIDGARD_URL=https://midgard.mayachain.info/v2 # foxy apr VITE_TOKEMAK_STATS_URL=https://stats.tokemaklabs.com/ diff --git a/.env.development b/.env.development index b9cf13a59d2..99401bfa55b 100644 --- a/.env.development +++ b/.env.development @@ -67,14 +67,16 @@ VITE_HYPEREVM_NODE_URL=https://rpc.hyperliquid.xyz/evm # Swap me back to SS as-needed # VITE_THORCHAIN_NODE_URL=https://dev-api.thorchain.shapeshift.com/lcd VITE_THORCHAIN_NODE_URL=https://thornode.ninerealms.com -VITE_MAYACHAIN_NODE_URL=https://dev-api.mayachain.shapeshift.com/lcd +# VITE_MAYACHAIN_NODE_URL=https://dev-api.mayachain.shapeshift.com/lcd +VITE_MAYACHAIN_NODE_URL=https://mayanode.mayachain.info VITE_SOLANA_NODE_URL=https://dev-api.solana.shapeshift.com/api/v1/jsonrpc VITE_TRON_NODE_URL=https://api.trongrid.io # midgard # VITE_THORCHAIN_MIDGARD_URL=https://dev-api.thorchain.shapeshift.com/midgard/v2 VITE_THORCHAIN_MIDGARD_URL=https://midgard.ninerealms.com/v2 -VITE_MAYACHAIN_MIDGARD_URL=https://dev-api.mayachain.shapeshift.com/midgard/v2 +# VITE_MAYACHAIN_MIDGARD_URL=https://dev-api.mayachain.shapeshift.com/midgard/v2 +VITE_MAYACHAIN_MIDGARD_URL=https://midgard.mayachain.info/v2 NODE_ENV=development diff --git a/package.json b/package.json index eb459fa3ddf..086316a2b9c 100644 --- a/package.json +++ b/package.json @@ -100,24 +100,24 @@ "@shapeshiftoss/chain-adapters": "workspace:^", "@shapeshiftoss/contracts": "workspace:^", "@shapeshiftoss/errors": "workspace:^", - "@shapeshiftoss/hdwallet-coinbase": "1.62.32", - "@shapeshiftoss/hdwallet-core": "1.62.32", - "@shapeshiftoss/hdwallet-gridplus": "1.62.32", - "@shapeshiftoss/hdwallet-keepkey": "1.62.32", - "@shapeshiftoss/hdwallet-keepkey-webusb": "1.62.32", - "@shapeshiftoss/hdwallet-keplr": "1.62.32", - "@shapeshiftoss/hdwallet-ledger": "1.62.32", - "@shapeshiftoss/hdwallet-ledger-webhid": "1.62.32", - "@shapeshiftoss/hdwallet-ledger-webusb": "1.62.32", - "@shapeshiftoss/hdwallet-metamask-multichain": "1.62.32", - "@shapeshiftoss/hdwallet-native": "1.62.32", - "@shapeshiftoss/hdwallet-native-vault": "1.62.32", - "@shapeshiftoss/hdwallet-phantom": "1.62.32", - "@shapeshiftoss/hdwallet-trezor": "1.62.32", - "@shapeshiftoss/hdwallet-trezor-connect": "1.62.32", - "@shapeshiftoss/hdwallet-vultisig": "1.62.32", - "@shapeshiftoss/hdwallet-walletconnect": "1.62.32", - "@shapeshiftoss/hdwallet-walletconnectv2": "1.62.32", + "@shapeshiftoss/hdwallet-coinbase": "1.62.35", + "@shapeshiftoss/hdwallet-core": "1.62.35", + "@shapeshiftoss/hdwallet-gridplus": "1.62.35", + "@shapeshiftoss/hdwallet-keepkey": "1.62.35", + "@shapeshiftoss/hdwallet-keepkey-webusb": "1.62.35", + "@shapeshiftoss/hdwallet-keplr": "1.62.35", + "@shapeshiftoss/hdwallet-ledger": "1.62.35", + "@shapeshiftoss/hdwallet-ledger-webhid": "1.62.35", + "@shapeshiftoss/hdwallet-ledger-webusb": "1.62.35", + "@shapeshiftoss/hdwallet-metamask-multichain": "1.62.35", + "@shapeshiftoss/hdwallet-native": "1.62.35", + "@shapeshiftoss/hdwallet-native-vault": "1.62.35", + "@shapeshiftoss/hdwallet-phantom": "1.62.35", + "@shapeshiftoss/hdwallet-trezor": "1.62.35", + "@shapeshiftoss/hdwallet-trezor-connect": "1.62.35", + "@shapeshiftoss/hdwallet-vultisig": "1.62.35", + "@shapeshiftoss/hdwallet-walletconnect": "1.62.35", + "@shapeshiftoss/hdwallet-walletconnectv2": "1.62.35", "@shapeshiftoss/swapper": "workspace:^", "@shapeshiftoss/types": "workspace:^", "@shapeshiftoss/unchained-client": "workspace:^", diff --git a/packages/chain-adapters/package.json b/packages/chain-adapters/package.json index 759628d6479..9c1bb71cf82 100644 --- a/packages/chain-adapters/package.json +++ b/packages/chain-adapters/package.json @@ -31,8 +31,8 @@ "dependencies": { "@mysten/sui": "1.45.0", "@shapeshiftoss/caip": "workspace:^", - "@shapeshiftoss/hdwallet-core": "1.62.32", - "@shapeshiftoss/hdwallet-ledger": "1.62.32", + "@shapeshiftoss/hdwallet-core": "1.62.35", + "@shapeshiftoss/hdwallet-ledger": "1.62.35", "@shapeshiftoss/types": "workspace:^", "@shapeshiftoss/unchained-client": "workspace:^", "@shapeshiftoss/utils": "workspace:^", diff --git a/packages/chain-adapters/src/cosmossdk/mayachain/MayachainChainAdapter.ts b/packages/chain-adapters/src/cosmossdk/mayachain/MayachainChainAdapter.ts index c6b59c4e930..45fa97dd5b4 100644 --- a/packages/chain-adapters/src/cosmossdk/mayachain/MayachainChainAdapter.ts +++ b/packages/chain-adapters/src/cosmossdk/mayachain/MayachainChainAdapter.ts @@ -1,5 +1,9 @@ import type { AssetId } from '@shapeshiftoss/caip' -import { ASSET_REFERENCE, mayachainAssetId } from '@shapeshiftoss/caip' +import { + ASSET_REFERENCE, + generateAssetIdFromCosmosSdkDenom, + mayachainAssetId, +} from '@shapeshiftoss/caip' import type { HDWallet, MayachainSignTx, MayachainWallet } from '@shapeshiftoss/hdwallet-core' import { supportsMayachain } from '@shapeshiftoss/hdwallet-core' import type { RootBip44Params } from '@shapeshiftoss/types' @@ -8,6 +12,8 @@ import * as unchained from '@shapeshiftoss/unchained-client' import { ChainAdapterError, ErrorHandler } from '../../error/ErrorHandler' import type { + Account, + BroadcastTransactionInput, BuildDepositTxInput, BuildSendApiTxInput, BuildSendTxInput, @@ -34,6 +40,7 @@ const DEFAULT_CHAIN_ID = KnownChainIds.MayachainMainnet export interface ChainAdapterArgs extends BaseChainAdapterArgs { midgardUrl: string + nodeUrl: string } export class ChainAdapter extends CosmosSdkBaseAdapter { @@ -43,6 +50,8 @@ export class ChainAdapter extends CosmosSdkBaseAdapter> { + try { + const [authRes, balanceRes] = await Promise.all([ + fetch(`${this.nodeUrl}/cosmos/auth/v1beta1/accounts/${pubkey}`), + fetch(`${this.nodeUrl}/cosmos/bank/v1beta1/balances/${pubkey}`), + ]) + + if (!authRes.ok) { + throw new Error(`Failed to fetch account: ${authRes.status} ${authRes.statusText}`) + } + if (!balanceRes.ok) { + throw new Error(`Failed to fetch balances: ${balanceRes.status} ${balanceRes.statusText}`) + } + + const authData = (await authRes.json()) as { + account: { account_number: string; sequence: string; pub_key?: { key: string } } + } + const balanceData = (await balanceRes.json()) as { + balances: { denom: string; amount: string }[] + } + + const assets = balanceData.balances.reduce<{ amount: string; assetId: AssetId }[]>( + (acc, b) => { + if (b.denom === this.denom) return acc + try { + acc.push({ + amount: b.amount, + assetId: generateAssetIdFromCosmosSdkDenom(b.denom), + }) + } catch {} + return acc + }, + [], + ) + + const nativeBalance = balanceData.balances.find(b => b.denom === this.denom)?.amount ?? '0' + + return { + balance: nativeBalance, + pubkey, + chainId: this.chainId, + assetId: this.assetId, + chain: this.getType(), + chainSpecific: { + accountNumber: authData.account.account_number, + sequence: authData.account.sequence, + assets, + delegations: [], + redelegations: [], + undelegations: [], + rewards: [], + }, + } as Account + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.getAccount', + options: { pubkey }, + }) + } + } + + async broadcastTransaction({ + senderAddress, + receiverAddress, + hex, + }: BroadcastTransactionInput): Promise { + try { + await Promise.all([ + assertAddressNotSanctioned(senderAddress), + receiverAddress !== CONTRACT_INTERACTION && assertAddressNotSanctioned(receiverAddress), + ]) + + const response = await fetch(`${this.nodeUrl}/cosmos/tx/v1beta1/txs`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + tx_bytes: hex, + mode: 'BROADCAST_MODE_SYNC', + }), + }) + + const data = (await response.json()) as { + tx_response?: { code: number; txhash: string; raw_log?: string } + } + + if (data.tx_response?.code !== 0) { + throw new Error(data.tx_response?.raw_log || 'Broadcast failed') + } + + return data.tx_response.txhash + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.broadcastTransaction', + }) + } + } } diff --git a/packages/chain-adapters/src/cosmossdk/mayachain/SecondClassMayachainAdapter.ts b/packages/chain-adapters/src/cosmossdk/mayachain/SecondClassMayachainAdapter.ts new file mode 100644 index 00000000000..6245cc811f5 --- /dev/null +++ b/packages/chain-adapters/src/cosmossdk/mayachain/SecondClassMayachainAdapter.ts @@ -0,0 +1,637 @@ +import type { AssetId } from '@shapeshiftoss/caip' +import { + ASSET_REFERENCE, + fromChainId, + generateAssetIdFromCosmosSdkDenom, + mayachainAssetId, +} from '@shapeshiftoss/caip' +import type { HDWallet, MayachainSignTx, MayachainWallet } from '@shapeshiftoss/hdwallet-core' +import { supportsMayachain } from '@shapeshiftoss/hdwallet-core' +import type { Bip44Params, RootBip44Params } from '@shapeshiftoss/types' +import { KnownChainIds } from '@shapeshiftoss/types' +import { TransferType, TxStatus } from '@shapeshiftoss/unchained-client' +import { bech32 } from 'bech32' + +import type { ChainAdapter as IChainAdapter } from '../../api' +import { ChainAdapterError, ErrorHandler } from '../../error/ErrorHandler' +import type { + Account, + BroadcastTransactionInput, + BuildDepositTxInput, + BuildSendApiTxInput, + BuildSendTxInput, + FeeDataEstimate, + GetAddressInput, + GetBip44ParamsInput, + GetFeeDataInput, + SignAndBroadcastTransactionInput, + SignTxInput, + SubscribeError, + SubscribeTxsInput, + Transaction, + TxHistoryInput, + TxHistoryResponse, + ValidAddressResult, +} from '../../types' +import { ChainAdapterDisplayName, CONTRACT_INTERACTION, ValidAddressResultType } from '../../types' +import { toAddressNList, verifyLedgerAppOpen } from '../../utils' +import { bnOrZero } from '../../utils/bignumber' +import { assertAddressNotSanctioned } from '../../utils/validateAddress' +import type { + BuildTransactionInput, + CosmosSDKToken, + MayachainMsgDeposit, + MayachainMsgSend, +} from '../types' +import { MayachainMessageType } from '../types' + +const NATIVE_FEE = '2000000000' + +export type SecondClassMayachainAdapterArgs = { + nodeUrl: string + midgardUrl: string +} + +export class SecondClassMayachainAdapter implements IChainAdapter { + public static readonly rootBip44Params: RootBip44Params = { + purpose: 44, + coinType: Number(ASSET_REFERENCE.Mayachain), + accountNumber: 0, + } + + protected readonly nodeUrl: string + protected readonly midgardUrl: string + protected readonly assetId: AssetId = mayachainAssetId + protected readonly chainId = KnownChainIds.MayachainMainnet + protected readonly denom = 'cacao' + + constructor(args: SecondClassMayachainAdapterArgs) { + this.nodeUrl = args.nodeUrl + this.midgardUrl = args.midgardUrl + } + + private assertSupportsChain(wallet: HDWallet): asserts wallet is MayachainWallet { + if (!supportsMayachain(wallet)) { + throw new ChainAdapterError(`wallet does not support: ${this.getDisplayName()}`, { + translation: 'chainAdapters.errors.unsupportedChain', + options: { chain: this.getDisplayName() }, + }) + } + } + + getDisplayName() { + return ChainAdapterDisplayName.Mayachain + } + + getName() { + const enumIndex = Object.values(ChainAdapterDisplayName).indexOf( + ChainAdapterDisplayName.Mayachain, + ) + return Object.keys(ChainAdapterDisplayName)[enumIndex] + } + + getType(): KnownChainIds.MayachainMainnet { + return KnownChainIds.MayachainMainnet + } + + getChainId() { + return this.chainId + } + + getFeeAssetId(): AssetId { + return this.assetId + } + + getBip44Params({ accountNumber }: GetBip44ParamsInput): Bip44Params { + if (accountNumber < 0) throw new Error('accountNumber must be >= 0') + return { + ...SecondClassMayachainAdapter.rootBip44Params, + accountNumber, + isChange: false, + addressIndex: 0, + } + } + + async getAddress(input: GetAddressInput): Promise { + try { + const { wallet, accountNumber, pubKey, showOnDevice = false } = input + + if (pubKey) return pubKey + + if (!wallet) throw new Error('wallet is required') + this.assertSupportsChain(wallet) + await verifyLedgerAppOpen(this.chainId, wallet) + + const bip44Params = this.getBip44Params({ accountNumber }) + const address = await wallet.mayachainGetAddress({ + addressNList: toAddressNList(bip44Params), + showDisplay: showOnDevice, + }) + + if (!address) throw new Error('error getting address from wallet') + + return address + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.getAddress', + }) + } + } + + // eslint-disable-next-line require-await + async validateAddress(address: string): Promise { + const MAYACHAIN_PREFIX = 'maya' + + try { + const decoded = bech32.decode(address) + if (decoded.prefix !== MAYACHAIN_PREFIX) { + return { valid: false, result: ValidAddressResultType.Invalid } + } + + return { valid: true, result: ValidAddressResultType.Valid } + } catch { + return { valid: false, result: ValidAddressResultType.Invalid } + } + } + + async getAccount(pubkey: string): Promise> { + try { + const [authRes, balanceRes] = await Promise.all([ + fetch(`${this.nodeUrl}/cosmos/auth/v1beta1/accounts/${pubkey}`), + fetch(`${this.nodeUrl}/cosmos/bank/v1beta1/balances/${pubkey}`), + ]) + + if (!authRes.ok) { + throw new Error(`Failed to fetch account: ${authRes.status} ${authRes.statusText}`) + } + if (!balanceRes.ok) { + throw new Error(`Failed to fetch balances: ${balanceRes.status} ${balanceRes.statusText}`) + } + + const authData = (await authRes.json()) as { + account: { account_number: string; sequence: string; pub_key?: { key: string } } + } + const balanceData = (await balanceRes.json()) as { + balances: { denom: string; amount: string }[] + } + + const assets = balanceData.balances.reduce((acc, b) => { + if (b.denom === this.denom) return acc + try { + acc.push({ + amount: b.amount, + assetId: generateAssetIdFromCosmosSdkDenom(b.denom), + }) + } catch {} + return acc + }, []) + + const nativeBalance = balanceData.balances.find(b => b.denom === this.denom)?.amount ?? '0' + + return { + balance: nativeBalance, + pubkey, + chainId: this.chainId, + assetId: this.assetId, + chain: this.getType(), + chainSpecific: { + accountNumber: authData.account.account_number, + sequence: authData.account.sequence, + assets, + delegations: [], + redelegations: [], + undelegations: [], + rewards: [], + }, + } as Account + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.getAccount', + options: { pubkey }, + }) + } + } + + async broadcastTransaction({ + senderAddress, + receiverAddress, + hex, + }: BroadcastTransactionInput): Promise { + try { + await Promise.all([ + assertAddressNotSanctioned(senderAddress), + receiverAddress !== CONTRACT_INTERACTION && assertAddressNotSanctioned(receiverAddress), + ]) + + const response = await fetch(`${this.nodeUrl}/cosmos/tx/v1beta1/txs`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + tx_bytes: hex, + mode: 'BROADCAST_MODE_SYNC', + }), + }) + + const data = (await response.json()) as { + tx_response?: { code: number; txhash: string; raw_log?: string } + } + + if (data.tx_response?.code !== 0) { + throw new Error(data.tx_response?.raw_log || 'Broadcast failed') + } + + return data.tx_response.txhash + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.broadcastTransaction', + }) + } + } + + async signTransaction(signTxInput: SignTxInput): Promise { + try { + const { txToSign, wallet } = signTxInput + + if (!wallet) throw new Error('wallet is required') + this.assertSupportsChain(wallet) + await verifyLedgerAppOpen(this.chainId, wallet) + + const signedTx = await wallet.mayachainSignTx(txToSign) + + if (!signedTx?.serialized) throw new Error('error signing tx') + + return signedTx.serialized + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.signTransaction', + }) + } + } + + async signAndBroadcastTransaction({ + senderAddress, + receiverAddress, + signTxInput, + }: SignAndBroadcastTransactionInput): Promise { + try { + const { wallet } = signTxInput + + await Promise.all([ + assertAddressNotSanctioned(senderAddress), + receiverAddress !== CONTRACT_INTERACTION && assertAddressNotSanctioned(receiverAddress), + ]) + + if (!wallet) throw new Error('wallet is required') + this.assertSupportsChain(wallet) + + const hex = await this.signTransaction(signTxInput) + const txHash = await this.broadcastTransaction({ senderAddress, receiverAddress, hex }) + + return txHash + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.signAndBroadcastTransaction', + }) + } + } + + protected getAmount({ + account, + value, + fee, + sendMax, + }: { + account: Account + value: string + fee: string + sendMax?: boolean + }) { + if (!sendMax) return value + + const availableBalance = bnOrZero(account.balance).minus(fee) + + if (!availableBalance.isFinite() || availableBalance.lte(0)) { + throw new Error(`not enough balance to send: ${availableBalance.toString()}`) + } + + return availableBalance.toString() + } + + protected buildTransaction(input: BuildTransactionInput): { + txToSign: MayachainSignTx + } { + const { account, accountNumber, msg, memo = '', chainSpecific } = input + const { gas, fee } = chainSpecific + + const bip44Params = this.getBip44Params({ accountNumber }) + + const unsignedTx = { + fee: { amount: [{ amount: bnOrZero(fee).toString(), denom: this.denom }], gas }, + msg: [msg], + signatures: [], + memo, + } + + const txToSign = { + addressNList: toAddressNList(bip44Params), + tx: unsignedTx, + chain_id: fromChainId(this.getType()).chainReference, + account_number: account.chainSpecific.accountNumber, + sequence: account.chainSpecific.sequence, + } as unknown as MayachainSignTx + + return { txToSign } + } + + async buildSendApiTransaction( + input: BuildSendApiTxInput, + ): Promise<{ txToSign: MayachainSignTx }> { + try { + const { sendMax, to, value, from } = input + + const account = await this.getAccount(from) + const amount = this.getAmount({ account, value, fee: NATIVE_FEE, sendMax }) + + const msg: MayachainMsgSend = { + type: MayachainMessageType.MsgSend, + value: { + amount: [{ amount, denom: this.denom }], + from_address: from, + to_address: to, + }, + } + + const tx = Object.assign(input, { + account, + msg, + chainSpecific: { ...input.chainSpecific, fee: '0' }, + }) + + return this.buildTransaction(tx) + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.buildTransaction', + }) + } + } + + async buildSendTransaction( + input: BuildSendTxInput, + ): Promise<{ txToSign: MayachainSignTx }> { + try { + const { accountNumber, wallet } = input + + const from = await this.getAddress({ accountNumber, wallet }) + const tx = await this.buildSendApiTransaction({ ...input, from }) + + return tx + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.buildTransaction', + }) + } + } + + async buildDepositTransaction( + input: BuildDepositTxInput, + ): Promise<{ txToSign: MayachainSignTx }> { + try { + const { from, value, memo } = input + + const account = await this.getAccount(from) + + const msg: MayachainMsgDeposit = { + type: MayachainMessageType.MsgDeposit, + value: { + coins: [{ asset: 'MAYA.CACAO', amount: bnOrZero(value).toString() }], + memo, + signer: from, + }, + } + + const tx = Object.assign(input, { + account, + msg, + chainSpecific: { ...input.chainSpecific, fee: '0' }, + }) + + return this.buildTransaction(tx) + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.buildTransaction', + }) + } + } + + // eslint-disable-next-line require-await + async getFeeData( + _: Partial>, + ): Promise> { + return { + fast: { txFee: NATIVE_FEE, chainSpecific: { gasLimit: '500000' } }, + average: { txFee: NATIVE_FEE, chainSpecific: { gasLimit: '500000' } }, + slow: { txFee: NATIVE_FEE, chainSpecific: { gasLimit: '500000' } }, + } + } + + getTxHistory(_input: TxHistoryInput): Promise { + return Promise.resolve({ + cursor: '', + pubkey: _input.pubkey, + transactions: [], + txIds: [], + }) + } + + subscribeTxs( + _input: SubscribeTxsInput, + _onMessage: (msg: Transaction) => void, + _onError: (err: SubscribeError) => void, + ): Promise { + return Promise.resolve() + } + + unsubscribeTxs(_input?: SubscribeTxsInput): void { + return + } + + closeTxs(): void { + return + } + + async parseTx(txHash: unknown, pubkey: string): Promise { + const hash = txHash as string + + const getAssetIdFromDenom = (denom: string): AssetId => { + const normalizedDenom = denom.toLowerCase().replace('maya.', '') + if (normalizedDenom === this.denom) return this.assetId + try { + return generateAssetIdFromCosmosSdkDenom(normalizedDenom) + } catch { + return this.assetId + } + } + + const response = await fetch(`${this.nodeUrl}/cosmos/tx/v1beta1/txs/${hash}`) + + if (response.ok) { + const data = (await response.json()) as { + tx_response: { + txhash: string + height: string + code: number + timestamp: string + tx: { + body: { + messages: { + '@type': string + from_address?: string + to_address?: string + amount?: { denom: string; amount: string }[] + coins?: { asset: string; amount: string }[] + memo?: string + signer?: string + }[] + memo?: string + } + } + } + } + + const txResponse = data.tx_response + const messages = txResponse.tx.body.messages + const status = txResponse.code === 0 ? TxStatus.Confirmed : TxStatus.Failed + const blockHeight = parseInt(txResponse.height, 10) + const blockTime = Math.floor(new Date(txResponse.timestamp).getTime() / 1000) + + const transfers: Transaction['transfers'] = [] + + for (const msg of messages) { + if (msg['@type'] === '/types.MsgSend' && msg.from_address && msg.to_address && msg.amount) { + for (const coin of msg.amount) { + const isSend = msg.from_address.toLowerCase() === pubkey.toLowerCase() + const isReceive = msg.to_address.toLowerCase() === pubkey.toLowerCase() + + if (isSend || isReceive) { + transfers.push({ + assetId: getAssetIdFromDenom(coin.denom), + from: [msg.from_address], + to: [msg.to_address], + type: isSend ? TransferType.Send : TransferType.Receive, + value: coin.amount, + }) + } + } + } else if (msg['@type'] === '/types.MsgDeposit' && msg.signer && msg.coins) { + for (const coin of msg.coins) { + const isSigner = msg.signer.toLowerCase() === pubkey.toLowerCase() + if (isSigner) { + transfers.push({ + assetId: getAssetIdFromDenom(coin.asset), + from: [msg.signer], + to: [msg.signer], + type: TransferType.Send, + value: coin.amount, + }) + } + } + } + } + + return { + txid: txResponse.txhash, + blockHash: '', + blockHeight, + blockTime, + confirmations: 1, + status, + chainId: this.chainId, + pubkey, + transfers, + data: txResponse.tx.body.memo + ? { parser: 'mayachain' as const, memo: txResponse.tx.body.memo } + : undefined, + } + } + + // Cosmos endpoint doesn't work for some txs, fall back to midgard + const midgardResponse = await fetch(`${this.midgardUrl}/actions?txid=${hash}`) + + if (!midgardResponse.ok) { + throw new Error( + `Failed to fetch transaction: ${midgardResponse.status} ${midgardResponse.statusText}`, + ) + } + + const midgardData = (await midgardResponse.json()) as { + actions: { + date: string + height: string + status: string + type: string + in: { address: string; coins: { amount: string; asset: string }[]; txID: string }[] + out: { address: string; coins: { amount: string; asset: string }[]; txID: string }[] + metadata?: { send?: { memo?: string }; swap?: { memo?: string } } + }[] + } + + if (!midgardData.actions?.length) { + throw new Error(`Transaction not found: ${hash}`) + } + + const action = midgardData.actions[0] + const status = action.status === 'success' ? TxStatus.Confirmed : TxStatus.Failed + const blockHeight = parseInt(action.height, 10) + const blockTime = Math.floor(parseInt(action.date, 10) / 1_000_000_000) + + const transfers: Transaction['transfers'] = [] + + for (const input of action.in) { + for (const coin of input.coins) { + const isSend = input.address.toLowerCase() === pubkey.toLowerCase() + if (isSend) { + transfers.push({ + assetId: getAssetIdFromDenom(coin.asset), + from: [input.address], + to: [action.out[0]?.address ?? input.address], + type: TransferType.Send, + value: coin.amount, + }) + } + } + } + + for (const output of action.out) { + for (const coin of output.coins) { + const isReceive = output.address.toLowerCase() === pubkey.toLowerCase() + const alreadyAdded = transfers.some( + t => t.type === TransferType.Send && t.to.includes(output.address), + ) + if (isReceive && !alreadyAdded) { + transfers.push({ + assetId: getAssetIdFromDenom(coin.asset), + from: [action.in[0]?.address ?? output.address], + to: [output.address], + type: TransferType.Receive, + value: coin.amount, + }) + } + } + } + + const memo = action.metadata?.send?.memo ?? action.metadata?.swap?.memo + + return { + txid: hash, + blockHash: '', + blockHeight, + blockTime, + confirmations: 1, + status, + chainId: this.chainId, + pubkey, + transfers, + data: memo ? { parser: 'mayachain' as const, memo } : undefined, + } + } +} diff --git a/packages/chain-adapters/src/cosmossdk/mayachain/index.ts b/packages/chain-adapters/src/cosmossdk/mayachain/index.ts index 222f0c85f09..f51d4f64712 100644 --- a/packages/chain-adapters/src/cosmossdk/mayachain/index.ts +++ b/packages/chain-adapters/src/cosmossdk/mayachain/index.ts @@ -1 +1,2 @@ export * from './MayachainChainAdapter' +export * from './SecondClassMayachainAdapter' diff --git a/packages/chain-adapters/src/cosmossdk/thorchain/SecondClassThorchainAdapter.ts b/packages/chain-adapters/src/cosmossdk/thorchain/SecondClassThorchainAdapter.ts new file mode 100644 index 00000000000..c6921bd600b --- /dev/null +++ b/packages/chain-adapters/src/cosmossdk/thorchain/SecondClassThorchainAdapter.ts @@ -0,0 +1,664 @@ +import type { AssetId } from '@shapeshiftoss/caip' +import { + ASSET_REFERENCE, + fromChainId, + generateAssetIdFromCosmosSdkDenom, + thorchainAssetId, +} from '@shapeshiftoss/caip' +import type { HDWallet, ThorchainSignTx, ThorchainWallet } from '@shapeshiftoss/hdwallet-core' +import { supportsThorchain } from '@shapeshiftoss/hdwallet-core' +import type { Bip44Params, RootBip44Params } from '@shapeshiftoss/types' +import { KnownChainIds } from '@shapeshiftoss/types' +import { TransferType, TxStatus } from '@shapeshiftoss/unchained-client' +import { bech32 } from 'bech32' + +import type { ChainAdapter as IChainAdapter } from '../../api' +import { ChainAdapterError, ErrorHandler } from '../../error/ErrorHandler' +import type { + Account, + BroadcastTransactionInput, + BuildDepositTxInput, + BuildSendApiTxInput, + BuildSendTxInput, + FeeDataEstimate, + GetAddressInput, + GetBip44ParamsInput, + GetFeeDataInput, + SignAndBroadcastTransactionInput, + SignTxInput, + SubscribeError, + SubscribeTxsInput, + Transaction, + TxHistoryInput, + TxHistoryResponse, + ValidAddressResult, +} from '../../types' +import { ChainAdapterDisplayName, CONTRACT_INTERACTION, ValidAddressResultType } from '../../types' +import { toAddressNList, verifyLedgerAppOpen } from '../../utils' +import { bnOrZero } from '../../utils/bignumber' +import { assertAddressNotSanctioned } from '../../utils/validateAddress' +import type { + BuildTransactionInput, + CosmosSDKToken, + ThorchainMsgDeposit, + ThorchainMsgSend, + ThorSupportedCoin, +} from '../types' +import { ThorchainMessageType } from '../types' + +const NATIVE_FEE = '2000000' + +const calculateFee = (fee: string): string => { + const feeMinusAutomaticOutboundFee = bnOrZero(fee).minus(NATIVE_FEE) + return feeMinusAutomaticOutboundFee.gt(0) ? feeMinusAutomaticOutboundFee.toString() : '0' +} + +export type SecondClassThorchainAdapterArgs = { + nodeUrl: string + thorMidgardUrl: string + mayaMidgardUrl: string +} + +export class SecondClassThorchainAdapter implements IChainAdapter { + public static readonly rootBip44Params: RootBip44Params = { + purpose: 44, + coinType: Number(ASSET_REFERENCE.Thorchain), + accountNumber: 0, + } + + protected readonly nodeUrl: string + protected readonly thorMidgardUrl: string + protected readonly assetId: AssetId = thorchainAssetId + protected readonly chainId = KnownChainIds.ThorchainMainnet + protected readonly denom = 'rune' + + constructor(args: SecondClassThorchainAdapterArgs) { + this.nodeUrl = args.nodeUrl + this.thorMidgardUrl = args.thorMidgardUrl + } + + private assertSupportsChain(wallet: HDWallet): asserts wallet is ThorchainWallet { + if (!supportsThorchain(wallet)) { + throw new ChainAdapterError(`wallet does not support: ${this.getDisplayName()}`, { + translation: 'chainAdapters.errors.unsupportedChain', + options: { chain: this.getDisplayName() }, + }) + } + } + + getDisplayName() { + return ChainAdapterDisplayName.Thorchain + } + + getName() { + const enumIndex = Object.values(ChainAdapterDisplayName).indexOf( + ChainAdapterDisplayName.Thorchain, + ) + return Object.keys(ChainAdapterDisplayName)[enumIndex] + } + + getType(): KnownChainIds.ThorchainMainnet { + return KnownChainIds.ThorchainMainnet + } + + getChainId() { + return this.chainId + } + + getFeeAssetId(): AssetId { + return this.assetId + } + + getBip44Params({ accountNumber }: GetBip44ParamsInput): Bip44Params { + if (accountNumber < 0) throw new Error('accountNumber must be >= 0') + return { + ...SecondClassThorchainAdapter.rootBip44Params, + accountNumber, + isChange: false, + addressIndex: 0, + } + } + + async getAddress(input: GetAddressInput): Promise { + try { + const { wallet, accountNumber, pubKey, showOnDevice = false } = input + + if (pubKey) return pubKey + + if (!wallet) throw new Error('wallet is required') + this.assertSupportsChain(wallet) + await verifyLedgerAppOpen(this.chainId, wallet) + + const bip44Params = this.getBip44Params({ accountNumber }) + const address = await wallet.thorchainGetAddress({ + addressNList: toAddressNList(bip44Params), + showDisplay: showOnDevice, + }) + + if (!address) throw new Error('error getting address from wallet') + + return address + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.getAddress', + }) + } + } + + // eslint-disable-next-line require-await + async validateAddress(address: string): Promise { + const THORCHAIN_PREFIX = 'thor' + + try { + const decoded = bech32.decode(address) + if (decoded.prefix !== THORCHAIN_PREFIX) { + return { valid: false, result: ValidAddressResultType.Invalid } + } + + const wordsLength = decoded.words.length + if (wordsLength !== 32) { + return { valid: false, result: ValidAddressResultType.Invalid } + } + return { valid: true, result: ValidAddressResultType.Valid } + } catch { + return { valid: false, result: ValidAddressResultType.Invalid } + } + } + + async getAccount(pubkey: string): Promise> { + try { + const [authRes, balanceRes] = await Promise.all([ + fetch(`${this.nodeUrl}/cosmos/auth/v1beta1/accounts/${pubkey}`), + fetch(`${this.nodeUrl}/cosmos/bank/v1beta1/balances/${pubkey}`), + ]) + + if (!authRes.ok) { + throw new Error(`Failed to fetch account: ${authRes.status} ${authRes.statusText}`) + } + if (!balanceRes.ok) { + throw new Error(`Failed to fetch balances: ${balanceRes.status} ${balanceRes.statusText}`) + } + + const authData = (await authRes.json()) as { + account: { account_number: string; sequence: string; pub_key?: { key: string } } + } + const balanceData = (await balanceRes.json()) as { + balances: { denom: string; amount: string }[] + } + + const assets = balanceData.balances.reduce((acc, b) => { + if (b.denom === this.denom) return acc + try { + acc.push({ + amount: b.amount, + assetId: generateAssetIdFromCosmosSdkDenom(b.denom), + }) + } catch {} + return acc + }, []) + + const nativeBalance = balanceData.balances.find(b => b.denom === this.denom)?.amount ?? '0' + + return { + balance: nativeBalance, + pubkey, + chainId: this.chainId, + assetId: this.assetId, + chain: this.getType(), + chainSpecific: { + accountNumber: authData.account.account_number, + sequence: authData.account.sequence, + assets, + delegations: [], + redelegations: [], + undelegations: [], + rewards: [], + }, + } as Account + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.getAccount', + options: { pubkey }, + }) + } + } + + async broadcastTransaction({ + senderAddress, + receiverAddress, + hex, + }: BroadcastTransactionInput): Promise { + try { + await Promise.all([ + assertAddressNotSanctioned(senderAddress), + receiverAddress !== CONTRACT_INTERACTION && assertAddressNotSanctioned(receiverAddress), + ]) + + const response = await fetch(`${this.nodeUrl}/cosmos/tx/v1beta1/txs`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + tx_bytes: hex, + mode: 'BROADCAST_MODE_SYNC', + }), + }) + + const data = (await response.json()) as { + tx_response?: { code: number; txhash: string; raw_log?: string } + } + + if (data.tx_response?.code !== 0) { + throw new Error(data.tx_response?.raw_log || 'Broadcast failed') + } + + return data.tx_response.txhash + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.broadcastTransaction', + }) + } + } + + async signTransaction(signTxInput: SignTxInput): Promise { + try { + const { txToSign, wallet } = signTxInput + + this.assertSupportsChain(wallet) + await verifyLedgerAppOpen(this.chainId, wallet) + + const signedTx = await wallet.thorchainSignTx(txToSign) + + if (!signedTx?.serialized) throw new Error('error signing tx') + + return signedTx.serialized + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.signTransaction', + }) + } + } + + async signAndBroadcastTransaction({ + senderAddress, + receiverAddress, + signTxInput, + }: SignAndBroadcastTransactionInput): Promise { + try { + const { wallet } = signTxInput + + await Promise.all([ + assertAddressNotSanctioned(senderAddress), + receiverAddress !== CONTRACT_INTERACTION && assertAddressNotSanctioned(receiverAddress), + ]) + + this.assertSupportsChain(wallet) + + const hex = await this.signTransaction(signTxInput) + const txHash = await this.broadcastTransaction({ senderAddress, receiverAddress, hex }) + + return txHash + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.signAndBroadcastTransaction', + }) + } + } + + protected getAmount({ + account, + value, + fee, + sendMax, + }: { + account: Account + value: string + fee: string + sendMax?: boolean + }) { + if (!sendMax) return value + + const availableBalance = bnOrZero(account.balance).minus(fee) + + if (!availableBalance.isFinite() || availableBalance.lte(0)) { + throw new Error(`not enough balance to send: ${availableBalance.toString()}`) + } + + return availableBalance.toString() + } + + protected buildTransaction(input: BuildTransactionInput): { + txToSign: ThorchainSignTx + } { + const { account, accountNumber, msg, memo = '', chainSpecific } = input + const { gas, fee } = chainSpecific + + const bip44Params = this.getBip44Params({ accountNumber }) + + const unsignedTx = { + fee: { amount: [{ amount: bnOrZero(fee).toString(), denom: this.denom }], gas }, + msg: [msg], + signatures: [], + memo, + } + + const txToSign = { + addressNList: toAddressNList(bip44Params), + tx: unsignedTx, + chain_id: fromChainId(this.getType()).chainReference, + account_number: account.chainSpecific.accountNumber, + sequence: account.chainSpecific.sequence, + } as unknown as ThorchainSignTx + + return { txToSign } + } + + async buildSendApiTransaction( + input: BuildSendApiTxInput, + ): Promise<{ txToSign: ThorchainSignTx }> { + try { + const { sendMax, to, value, from, chainSpecific } = input + const { coin = 'THOR.RUNE', fee } = chainSpecific + + if (coin !== 'THOR.RUNE' && coin !== 'THOR.TCY' && coin !== 'THOR.RUJI') + throw new Error('unsupported coin type') + + if (!fee) throw new Error('fee is required') + + const account = await this.getAccount(from) + const amount = coin === 'THOR.RUNE' ? this.getAmount({ account, value, fee, sendMax }) : value + + const denom = (() => { + if (coin === 'THOR.TCY') return 'tcy' + if (coin === 'THOR.RUJI') return 'x/ruji' + return this.denom + })() + + const msg: ThorchainMsgSend = { + type: ThorchainMessageType.MsgSend, + value: { + amount: [{ amount, denom }], + from_address: from, + to_address: to, + }, + } + + const tx = Object.assign(input, { + account, + msg, + chainSpecific: { ...input.chainSpecific, fee: calculateFee(fee) }, + }) + + return this.buildTransaction(tx) + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.buildTransaction', + }) + } + } + + async buildSendTransaction( + input: BuildSendTxInput, + ): Promise<{ txToSign: ThorchainSignTx }> { + try { + const { accountNumber, wallet } = input + + const from = await this.getAddress({ accountNumber, wallet }) + const tx = await this.buildSendApiTransaction({ ...input, from }) + + return tx + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.buildTransaction', + }) + } + } + + async buildDepositTransaction( + input: BuildDepositTxInput, + ): Promise<{ txToSign: ThorchainSignTx }> { + try { + const { from, value, memo, chainSpecific } = input + const { fee, coin = 'THOR.RUNE' } = chainSpecific + + if (!['THOR.TCY', 'THOR.RUJI', 'THOR.RUNE'].includes(coin)) + throw new Error('unsupported coin type') + + if (!fee) throw new Error('fee is required') + + const account = await this.getAccount(from) + + const msg: ThorchainMsgDeposit = { + type: ThorchainMessageType.MsgDeposit, + value: { + coins: [{ asset: coin as ThorSupportedCoin, amount: bnOrZero(value).toString() }], + memo, + signer: from, + }, + } + + const tx = Object.assign(input, { + account, + msg, + chainSpecific: { ...input.chainSpecific, fee: calculateFee(fee) }, + }) + + return this.buildTransaction(tx) + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.buildTransaction', + }) + } + } + + // eslint-disable-next-line require-await + async getFeeData( + _: Partial>, + ): Promise> { + return { + fast: { txFee: NATIVE_FEE, chainSpecific: { gasLimit: '500000000' } }, + average: { txFee: NATIVE_FEE, chainSpecific: { gasLimit: '500000000' } }, + slow: { txFee: NATIVE_FEE, chainSpecific: { gasLimit: '500000000' } }, + } + } + + getTxHistory(_input: TxHistoryInput): Promise { + return Promise.resolve({ + cursor: '', + pubkey: _input.pubkey, + transactions: [], + txIds: [], + }) + } + + subscribeTxs( + _input: SubscribeTxsInput, + _onMessage: (msg: Transaction) => void, + _onError: (err: SubscribeError) => void, + ): Promise { + return Promise.resolve() + } + + unsubscribeTxs(_input?: SubscribeTxsInput): void { + return + } + + closeTxs(): void { + return + } + + async parseTx(txHash: unknown, pubkey: string): Promise { + const hash = txHash as string + + const getAssetIdFromDenom = (denom: string): AssetId => { + const normalizedDenom = denom.toLowerCase().replace('thor.', '') + if (normalizedDenom === this.denom) return this.assetId + try { + return generateAssetIdFromCosmosSdkDenom(normalizedDenom) + } catch { + return this.assetId + } + } + + const response = await fetch(`${this.nodeUrl}/cosmos/tx/v1beta1/txs/${hash}`) + + if (response.ok) { + const data = (await response.json()) as { + tx_response: { + txhash: string + height: string + code: number + timestamp: string + tx: { + body: { + messages: { + '@type': string + from_address?: string + to_address?: string + amount?: { denom: string; amount: string }[] + coins?: { asset: string; amount: string }[] + memo?: string + signer?: string + }[] + memo?: string + } + } + } + } + + const txResponse = data.tx_response + const messages = txResponse.tx.body.messages + const status = txResponse.code === 0 ? TxStatus.Confirmed : TxStatus.Failed + const blockHeight = parseInt(txResponse.height, 10) + const blockTime = Math.floor(new Date(txResponse.timestamp).getTime() / 1000) + + const transfers: Transaction['transfers'] = [] + + for (const msg of messages) { + if (msg['@type'] === '/types.MsgSend' && msg.from_address && msg.to_address && msg.amount) { + for (const coin of msg.amount) { + const isSend = msg.from_address.toLowerCase() === pubkey.toLowerCase() + const isReceive = msg.to_address.toLowerCase() === pubkey.toLowerCase() + + if (isSend || isReceive) { + transfers.push({ + assetId: getAssetIdFromDenom(coin.denom), + from: [msg.from_address], + to: [msg.to_address], + type: isSend ? TransferType.Send : TransferType.Receive, + value: coin.amount, + }) + } + } + } else if (msg['@type'] === '/types.MsgDeposit' && msg.signer && msg.coins) { + for (const coin of msg.coins) { + const isSigner = msg.signer.toLowerCase() === pubkey.toLowerCase() + if (isSigner) { + transfers.push({ + assetId: getAssetIdFromDenom(coin.asset), + from: [msg.signer], + to: [msg.signer], + type: TransferType.Send, + value: coin.amount, + }) + } + } + } + } + + return { + txid: txResponse.txhash, + blockHash: '', + blockHeight, + blockTime, + confirmations: 1, + status, + chainId: this.chainId, + pubkey, + transfers, + data: txResponse.tx.body.memo + ? { parser: 'thorchain' as const, memo: txResponse.tx.body.memo } + : undefined, + } + } + + // Cosmos endpoint doesn't work for some txs (e.g. TCY), fall back to midgard + const midgardResponse = await fetch(`${this.thorMidgardUrl}/actions?txid=${hash}`) + + if (!midgardResponse.ok) { + throw new Error( + `Failed to fetch transaction: ${midgardResponse.status} ${midgardResponse.statusText}`, + ) + } + + const midgardData = (await midgardResponse.json()) as { + actions: { + date: string + height: string + status: string + type: string + in: { address: string; coins: { amount: string; asset: string }[]; txID: string }[] + out: { address: string; coins: { amount: string; asset: string }[]; txID: string }[] + metadata?: { send?: { memo?: string }; swap?: { memo?: string } } + }[] + } + + if (!midgardData.actions?.length) { + throw new Error(`Transaction not found: ${hash}`) + } + + const action = midgardData.actions[0] + const status = action.status === 'success' ? TxStatus.Confirmed : TxStatus.Failed + const blockHeight = parseInt(action.height, 10) + const blockTime = Math.floor(parseInt(action.date, 10) / 1_000_000_000) + + const transfers: Transaction['transfers'] = [] + + for (const input of action.in) { + for (const coin of input.coins) { + const isSend = input.address.toLowerCase() === pubkey.toLowerCase() + if (isSend) { + transfers.push({ + assetId: getAssetIdFromDenom(coin.asset), + from: [input.address], + to: [action.out[0]?.address ?? input.address], + type: TransferType.Send, + value: coin.amount, + }) + } + } + } + + for (const output of action.out) { + for (const coin of output.coins) { + const isReceive = output.address.toLowerCase() === pubkey.toLowerCase() + const alreadyAdded = transfers.some( + t => t.type === TransferType.Send && t.to.includes(output.address), + ) + if (isReceive && !alreadyAdded) { + transfers.push({ + assetId: getAssetIdFromDenom(coin.asset), + from: [action.in[0]?.address ?? output.address], + to: [output.address], + type: TransferType.Receive, + value: coin.amount, + }) + } + } + } + + const memo = action.metadata?.send?.memo ?? action.metadata?.swap?.memo + + return { + txid: hash, + blockHash: '', + blockHeight, + blockTime, + confirmations: 1, + status, + chainId: this.chainId, + pubkey, + transfers, + data: memo ? { parser: 'thorchain' as const, memo } : undefined, + } + } +} diff --git a/packages/chain-adapters/src/cosmossdk/thorchain/ThorchainChainAdapter.ts b/packages/chain-adapters/src/cosmossdk/thorchain/ThorchainChainAdapter.ts index 11b547958f3..427c67ab84e 100644 --- a/packages/chain-adapters/src/cosmossdk/thorchain/ThorchainChainAdapter.ts +++ b/packages/chain-adapters/src/cosmossdk/thorchain/ThorchainChainAdapter.ts @@ -1,5 +1,9 @@ import type { AssetId } from '@shapeshiftoss/caip' -import { ASSET_REFERENCE, thorchainAssetId } from '@shapeshiftoss/caip' +import { + ASSET_REFERENCE, + generateAssetIdFromCosmosSdkDenom, + thorchainAssetId, +} from '@shapeshiftoss/caip' import type { HDWallet, ThorchainSignTx, ThorchainWallet } from '@shapeshiftoss/hdwallet-core' import { supportsThorchain } from '@shapeshiftoss/hdwallet-core' import type { RootBip44Params } from '@shapeshiftoss/types' @@ -10,6 +14,8 @@ import PQueue from 'p-queue' import { ChainAdapterError, ErrorHandler } from '../../error/ErrorHandler' import type { + Account, + BroadcastTransactionInput, BuildDepositTxInput, BuildSendApiTxInput, BuildSendTxInput, @@ -50,6 +56,7 @@ export interface ChainAdapterArgs extends BaseChainAdapterArgs { @@ -60,6 +67,7 @@ export class ChainAdapter extends CosmosSdkBaseAdapter> { + try { + const [authRes, balanceRes] = await Promise.all([ + fetch(`${this.nodeUrl}/cosmos/auth/v1beta1/accounts/${pubkey}`), + fetch(`${this.nodeUrl}/cosmos/bank/v1beta1/balances/${pubkey}`), + ]) + + if (!authRes.ok) { + throw new Error(`Failed to fetch account: ${authRes.status} ${authRes.statusText}`) + } + if (!balanceRes.ok) { + throw new Error(`Failed to fetch balances: ${balanceRes.status} ${balanceRes.statusText}`) + } + + const authData = (await authRes.json()) as { + account: { account_number: string; sequence: string; pub_key?: { key: string } } + } + const balanceData = (await balanceRes.json()) as { + balances: { denom: string; amount: string }[] + } + + const assets = balanceData.balances.reduce<{ amount: string; assetId: AssetId }[]>( + (acc, b) => { + if (b.denom === this.denom) return acc + try { + acc.push({ + amount: b.amount, + assetId: generateAssetIdFromCosmosSdkDenom(b.denom), + }) + } catch {} + return acc + }, + [], + ) + + const nativeBalance = balanceData.balances.find(b => b.denom === this.denom)?.amount ?? '0' + + return { + balance: nativeBalance, + pubkey, + chainId: this.chainId, + assetId: this.assetId, + chain: this.getType(), + chainSpecific: { + accountNumber: authData.account.account_number, + sequence: authData.account.sequence, + assets, + delegations: [], + redelegations: [], + undelegations: [], + rewards: [], + }, + } as Account + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.getAccount', + options: { pubkey }, + }) + } + } + + async broadcastTransaction({ + senderAddress, + receiverAddress, + hex, + }: BroadcastTransactionInput): Promise { + try { + await Promise.all([ + assertAddressNotSanctioned(senderAddress), + receiverAddress !== CONTRACT_INTERACTION && assertAddressNotSanctioned(receiverAddress), + ]) + + const response = await fetch(`${this.nodeUrl}/cosmos/tx/v1beta1/txs`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + tx_bytes: hex, + mode: 'BROADCAST_MODE_SYNC', + }), + }) + + const data = (await response.json()) as { + tx_response?: { code: number; txhash: string; raw_log?: string } + } + + if (data.tx_response?.code !== 0) { + throw new Error(data.tx_response?.raw_log || 'Broadcast failed') + } + + return data.tx_response.txhash + } catch (err) { + return ErrorHandler(err, { + translation: 'chainAdapters.errors.broadcastTransaction', + }) + } + } } diff --git a/packages/chain-adapters/src/cosmossdk/thorchain/index.ts b/packages/chain-adapters/src/cosmossdk/thorchain/index.ts index 6c16c2c70ce..05a9883f32e 100644 --- a/packages/chain-adapters/src/cosmossdk/thorchain/index.ts +++ b/packages/chain-adapters/src/cosmossdk/thorchain/index.ts @@ -1 +1,2 @@ export * from './ThorchainChainAdapter' +export * from './SecondClassThorchainAdapter' diff --git a/packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts b/packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts index 305c53eae3b..5562ba4a2ab 100644 --- a/packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts +++ b/packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts @@ -352,7 +352,9 @@ export abstract class UtxoBaseAdapter implements IChainAd if (!response.ok || data.error) { throw new Error(`Blockchair API error: ${data.error || response.statusText}`) } - return { hex: data.data[input.txid].raw_transaction } + return { + hex: data.data[input.txid].raw_transaction, + } } throw error } @@ -372,9 +374,12 @@ export abstract class UtxoBaseAdapter implements IChainAd txid: input.txid, hex: data.hex, // For Zcash, we need to pass the blockHeight and txid of each input transaction - // so Ledger can add them to the PSBT and determine the correct consensus branch ID + // so Ledger can add them to the PSBT and determine the correct consensus branch ID. + // Only pass blockHeight if it's a valid positive number (mempool txs have blockHeight: -1) ...(this.coinName === 'Zcash' && - 'blockHeight' in data && { blockHeight: data.blockHeight }), + 'blockHeight' in data && + typeof data.blockHeight === 'number' && + data.blockHeight > 0 && { blockHeight: data.blockHeight }), }) } diff --git a/packages/swapper/package.json b/packages/swapper/package.json index 54fba86bd9d..7648c51e96f 100644 --- a/packages/swapper/package.json +++ b/packages/swapper/package.json @@ -39,7 +39,7 @@ "@shapeshiftoss/caip": "workspace:^", "@shapeshiftoss/chain-adapters": "workspace:^", "@shapeshiftoss/contracts": "workspace:^", - "@shapeshiftoss/hdwallet-core": "1.62.32", + "@shapeshiftoss/hdwallet-core": "1.62.35", "@shapeshiftoss/types": "workspace:^", "@shapeshiftoss/unchained-client": "workspace:^", "@shapeshiftoss/utils": "workspace:^", diff --git a/packages/swapper/src/swappers/MayachainSwapper/endpoints.ts b/packages/swapper/src/swappers/MayachainSwapper/endpoints.ts index 96408f8653c..070d4590903 100644 --- a/packages/swapper/src/swappers/MayachainSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/MayachainSwapper/endpoints.ts @@ -90,8 +90,7 @@ export const mayachainApi: SwapperApi = { const { config } = input const nodeUrl = `${config.VITE_MAYACHAIN_NODE_URL}/mayachain` - const apiUrl = `${config.VITE_UNCHAINED_MAYACHAIN_HTTP_URL}/api/v1` - return checkTradeStatus({ ...input, nodeUrl, apiUrl, nativeChain: 'MAYA' }) + return checkTradeStatus({ ...input, nodeUrl, nativeChain: 'MAYA' }) }, } diff --git a/packages/swapper/src/swappers/ThorchainSwapper/endpoints.ts b/packages/swapper/src/swappers/ThorchainSwapper/endpoints.ts index ad20a1b0d4f..d3f2026512a 100644 --- a/packages/swapper/src/swappers/ThorchainSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ThorchainSwapper/endpoints.ts @@ -102,8 +102,7 @@ export const thorchainApi: SwapperApi = { const { config } = input const nodeUrl = `${config.VITE_THORCHAIN_NODE_URL}/thorchain` - const apiUrl = `${config.VITE_UNCHAINED_THORCHAIN_HTTP_URL}/api/v1` - return checkTradeStatus({ ...input, nodeUrl, apiUrl, nativeChain: 'THOR' }) + return checkTradeStatus({ ...input, nodeUrl, nativeChain: 'THOR' }) }, } diff --git a/packages/swapper/src/thorchain-utils/checkTradeStatus.ts b/packages/swapper/src/thorchain-utils/checkTradeStatus.ts index 27258f801f9..d88941f5667 100644 --- a/packages/swapper/src/thorchain-utils/checkTradeStatus.ts +++ b/packages/swapper/src/thorchain-utils/checkTradeStatus.ts @@ -1,5 +1,4 @@ import { mayachainChainId, thorchainChainId } from '@shapeshiftoss/caip' -import type { cosmossdk } from '@shapeshiftoss/unchained-client' import { TxStatus } from '@shapeshiftoss/unchained-client' import axios from 'axios' @@ -11,7 +10,6 @@ import type { ThornodeStatusResponse, ThornodeTxResponse } from './types' type CheckTradeStatusInputExtended = CheckTradeStatusInput & { nodeUrl: string - apiUrl: string nativeChain: 'THOR' | 'MAYA' } @@ -22,7 +20,6 @@ export const checkTradeStatus = async ({ fetchIsSmartContractAddressQuery, assertGetEvmChainAdapter, nodeUrl, - apiUrl, nativeChain, }: CheckTradeStatusInputExtended): Promise => { try { @@ -48,14 +45,21 @@ export const checkTradeStatus = async ({ (chainId === thorchainChainId && nativeChain === 'THOR') || (chainId === mayachainChainId && nativeChain === 'MAYA') ) { - const { data: tx } = await axios.get(`${apiUrl}/tx/${txHash}`) - - if (tx.events['0']?.error) { - return { - status: TxStatus.Failed, - buyTxHash: undefined, - message: tx.events[0].error.message, + try { + const cosmosNodeUrl = nodeUrl.replace('/thorchain', '').replace('/mayachain', '') + const { data: txResponse } = await axios.get<{ + tx_response?: { code: number; raw_log?: string } + }>(`${cosmosNodeUrl}/cosmos/tx/v1beta1/txs/${txHash}`) + + if (txResponse.tx_response && txResponse.tx_response.code !== 0) { + return { + status: TxStatus.Failed, + buyTxHash: undefined, + message: txResponse.tx_response.raw_log, + } } + } catch { + // Cosmos endpoint may 404 for some txs (e.g. MsgDeposit), continue with thorchain status check } } diff --git a/src/constants/chains.ts b/src/constants/chains.ts index f85da5128a6..af70c1e08df 100644 --- a/src/constants/chains.ts +++ b/src/constants/chains.ts @@ -11,6 +11,8 @@ export const SECOND_CLASS_CHAINS: readonly KnownChainIds[] = [ KnownChainIds.MonadMainnet, KnownChainIds.HyperEvmMainnet, KnownChainIds.PlasmaMainnet, + KnownChainIds.ThorchainMainnet, + KnownChainIds.MayachainMainnet, ] // returns known ChainIds as an array, excluding the ones that are currently flagged off diff --git a/src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx b/src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx index a69ca814192..a61d84c7e59 100644 --- a/src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx +++ b/src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx @@ -12,9 +12,11 @@ import { getConfig } from '@/config' import { SECOND_CLASS_CHAINS } from '@/constants/chains' import { getChainAdapterManager } from '@/context/PluginProvider/chainAdapterSingleton' import { getHyperEvmTransactionStatus } from '@/lib/utils/hyperevm' +import { getMayachainTransactionStatus } from '@/lib/utils/mayachain' import { getMonadTransactionStatus } from '@/lib/utils/monad' import { getPlasmaTransactionStatus } from '@/lib/utils/plasma' import { getSuiTransactionStatus } from '@/lib/utils/sui' +import { getThorchainSendTransactionStatus } from '@/lib/utils/thorchain' import { getTronTransactionStatus } from '@/lib/utils/tron' import { actionSlice } from '@/state/slices/actionSlice/actionSlice' import { selectPendingWalletSendActions } from '@/state/slices/actionSlice/selectors' @@ -154,6 +156,18 @@ export const useSendActionSubscriber = () => { hyperEvmTxStatus === TxStatus.Confirmed || hyperEvmTxStatus === TxStatus.Failed break } + case KnownChainIds.ThorchainMainnet: { + const thorTxStatus = await getThorchainSendTransactionStatus(txHash) + isConfirmed = + thorTxStatus === TxStatus.Confirmed || thorTxStatus === TxStatus.Failed + break + } + case KnownChainIds.MayachainMainnet: { + const mayaTxStatus = await getMayachainTransactionStatus(txHash) + isConfirmed = + mayaTxStatus === TxStatus.Confirmed || mayaTxStatus === TxStatus.Failed + break + } default: console.error(`Unsupported second-class chain: ${chainId}`) return diff --git a/src/lib/utils/mayachain.ts b/src/lib/utils/mayachain.ts new file mode 100644 index 00000000000..85d81d8684f --- /dev/null +++ b/src/lib/utils/mayachain.ts @@ -0,0 +1,54 @@ +import type { ChainId } from '@shapeshiftoss/caip' +import { mayachainChainId } from '@shapeshiftoss/caip' +import type { mayachain } from '@shapeshiftoss/chain-adapters' +import type { KnownChainIds } from '@shapeshiftoss/types' +import { TxStatus } from '@shapeshiftoss/unchained-client' + +import { getConfig } from '@/config' +import { getChainAdapterManager } from '@/context/PluginProvider/chainAdapterSingleton' + +export const isMayachainChainAdapter = ( + chainAdapter: unknown, +): chainAdapter is mayachain.SecondClassMayachainAdapter => { + if (!chainAdapter || typeof chainAdapter !== 'object') return false + const adapter = chainAdapter as mayachain.SecondClassMayachainAdapter + if (typeof adapter.getChainId !== 'function') return false + return adapter.getChainId() === mayachainChainId +} + +export const assertGetMayachainChainAdapter = ( + chainId: ChainId | KnownChainIds, +): mayachain.SecondClassMayachainAdapter => { + const chainAdapterManager = getChainAdapterManager() + const adapter = chainAdapterManager.get(chainId) + + if (!isMayachainChainAdapter(adapter)) { + throw Error('invalid chain adapter') + } + + return adapter +} + +export const getMayachainTransactionStatus = async (txHash: string): Promise => { + try { + const nodeUrl = getConfig().VITE_MAYACHAIN_NODE_URL + const response = await fetch(`${nodeUrl}/cosmos/tx/v1beta1/txs/${txHash}`) + + if (!response.ok) { + if (response.status === 404) return TxStatus.Pending + return TxStatus.Unknown + } + + const data = (await response.json()) as { + tx_response?: { code: number; txhash: string } + } + + if (!data.tx_response) return TxStatus.Unknown + + if (data.tx_response.code === 0) return TxStatus.Confirmed + return TxStatus.Failed + } catch (error) { + console.error('Error getting MAYAChain transaction status:', error) + return TxStatus.Unknown + } +} diff --git a/src/lib/utils/thorchain/index.ts b/src/lib/utils/thorchain/index.ts index 4becff58d45..c54ca4ce1fa 100644 --- a/src/lib/utils/thorchain/index.ts +++ b/src/lib/utils/thorchain/index.ts @@ -38,6 +38,40 @@ import { poll } from '@/lib/poll/poll' import type { getThorchainLpPosition } from '@/pages/ThorChainLP/queries/queries' import { getThorchainSaversPosition } from '@/state/slices/opportunitiesSlice/resolvers/thorchainsavers/utils' +export const getThorchainSendTransactionStatus = async (txHash: string): Promise => { + try { + const nodeUrl = getConfig().VITE_THORCHAIN_NODE_URL + const response = await axios.get(`${nodeUrl}/cosmos/tx/v1beta1/txs/${txHash}`, { + validateStatus: () => true, + }) + + if (response.data?.tx_response) { + if (response.data.tx_response.code === 0) return TxStatus.Confirmed + return TxStatus.Failed + } + + // Cosmos endpoint doesn't work for MsgDeposit txs (RUNE/TCY/RUJI internal sends) + // Fall back to midgard + const midgardUrl = getConfig().VITE_THORCHAIN_MIDGARD_URL + const midgardResponse = await axios.get( + `${midgardUrl}/actions?txid=${txHash}`, + { validateStatus: () => true }, + ) + + if (midgardResponse.data?.actions?.length) { + const action = midgardResponse.data.actions[0] + if (action.status === 'success') return TxStatus.Confirmed + if (action.status === 'pending') return TxStatus.Pending + return TxStatus.Failed + } + + return TxStatus.Pending + } catch (error) { + console.error('Error getting THORChain send transaction status:', error) + return TxStatus.Unknown + } +} + export const getThorchainTransactionStatus = async ({ txHash, skipOutbound, diff --git a/src/plugins/mayachain/index.tsx b/src/plugins/mayachain/index.tsx index d8c22ca91b9..265b05e0c1f 100644 --- a/src/plugins/mayachain/index.tsx +++ b/src/plugins/mayachain/index.tsx @@ -1,6 +1,5 @@ import { mayachain } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' -import * as unchained from '@shapeshiftoss/unchained-client' import { getConfig } from '@/config' import type { Plugins } from '@/plugins/types' @@ -17,19 +16,8 @@ export default function register(): Plugins { [ KnownChainIds.MayachainMainnet, () => { - const http = new unchained.mayachain.V1Api( - new unchained.mayachain.Configuration({ - basePath: getConfig().VITE_UNCHAINED_MAYACHAIN_HTTP_URL, - }), - ) - - const ws = new unchained.ws.Client( - getConfig().VITE_UNCHAINED_MAYACHAIN_WS_URL, - ) - - return new mayachain.ChainAdapter({ - providers: { http, ws }, - coinName: 'Mayachain', + return new mayachain.SecondClassMayachainAdapter({ + nodeUrl: getConfig().VITE_MAYACHAIN_NODE_URL, midgardUrl: getConfig().VITE_MAYACHAIN_MIDGARD_URL, }) }, diff --git a/src/plugins/thorchain/index.tsx b/src/plugins/thorchain/index.tsx index 43d233b59cc..9a5285ea9c7 100644 --- a/src/plugins/thorchain/index.tsx +++ b/src/plugins/thorchain/index.tsx @@ -1,6 +1,5 @@ import { thorchain } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' -import * as unchained from '@shapeshiftoss/unchained-client' import { getConfig } from '@/config' import type { Plugins } from '@/plugins/types' @@ -17,28 +16,10 @@ export default function register(): Plugins { [ KnownChainIds.ThorchainMainnet, () => { - const http = new unchained.thorchain.V1Api( - new unchained.thorchain.Configuration({ - basePath: getConfig().VITE_UNCHAINED_THORCHAIN_HTTP_URL, - }), - ) - - const httpV1 = new unchained.thorchainV1.V1Api( - new unchained.thorchainV1.Configuration({ - basePath: getConfig().VITE_UNCHAINED_THORCHAIN_V1_HTTP_URL, - }), - ) - - const ws = new unchained.ws.Client( - getConfig().VITE_UNCHAINED_THORCHAIN_WS_URL, - ) - - return new thorchain.ChainAdapter({ - providers: { http, ws }, - coinName: 'Thorchain', + return new thorchain.SecondClassThorchainAdapter({ + nodeUrl: getConfig().VITE_THORCHAIN_NODE_URL, thorMidgardUrl: getConfig().VITE_THORCHAIN_MIDGARD_URL, mayaMidgardUrl: getConfig().VITE_MAYACHAIN_MIDGARD_URL, - httpV1, }) }, ], diff --git a/yarn.lock b/yarn.lock index 100fc42ba70..801c505ed68 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4090,59 +4090,6 @@ __metadata: languageName: node linkType: hard -"@bitgo/blake2b-wasm@npm:^3.2.3": - version: 3.2.3 - resolution: "@bitgo/blake2b-wasm@npm:3.2.3" - dependencies: - nanoassert: ^1.0.0 - checksum: f398ea78559486095bfa898fd4fd5d0a8f022ffbcd31732854cec9118967f695a009339a3b4bf2cef62a2a38b8d93d4781769b3516b15fb3b11a4f12177a1f21 - languageName: node - linkType: hard - -"@bitgo/blake2b@npm:^3.2.4": - version: 3.2.4 - resolution: "@bitgo/blake2b@npm:3.2.4" - dependencies: - "@bitgo/blake2b-wasm": ^3.2.3 - nanoassert: ^2.0.0 - checksum: 6ee6575873eb4af42de387dd698bac835a739eee6aefe642606a978bf79f75be7abb0a619bdbf2789dfa1cf2ef36083a4e3bf23ff5c8f701a04222c5304bbae4 - languageName: node - linkType: hard - -"@bitgo/secp256k1@npm:^1.7.0": - version: 1.7.0 - resolution: "@bitgo/secp256k1@npm:1.7.0" - dependencies: - "@brandonblack/musig": ^0.0.1-alpha.0 - "@noble/secp256k1": 1.6.3 - bip32: ^3.0.1 - create-hash: ^1.2.0 - create-hmac: ^1.1.7 - ecpair: "npm:@bitgo/ecpair@2.1.0-rc.0" - checksum: 3cca08733c2228887111a1486430deaa5bd619bfc2defb0ef28c2f26d33b95f30604ce306c386a1efa0c097ee35212bb401bbee06db4c59e03149b658f7244a9 - languageName: node - linkType: hard - -"@bitgo/utxo-lib@npm:^11.18.0": - version: 11.18.0 - resolution: "@bitgo/utxo-lib@npm:11.18.0" - dependencies: - "@bitgo/blake2b": ^3.2.4 - "@bitgo/secp256k1": ^1.7.0 - "@brandonblack/musig": ^0.0.1-alpha.0 - bech32: ^2.0.0 - bip174: "npm:@bitgo-forks/bip174@3.1.0-master.4" - bitcoin-ops: ^1.3.0 - bitcoinjs-lib: "npm:@bitgo-forks/bitcoinjs-lib@7.1.0-master.11" - bs58check: ^2.1.2 - cashaddress: ^1.1.0 - fastpriorityqueue: ^0.7.1 - typeforce: ^1.11.3 - varuint-bitcoin: ^1.1.2 - checksum: 4641a6dc8a342a828ec3a3dff420e79fd4ddf5ea47051cc66844155038323451ebe1b5e145289cd36e64eca70bbec0f35703be8461f3dca6d1ac7cce028210f3 - languageName: node - linkType: hard - "@bithighlander/bitcoin-cash-js-lib@npm:5.2.1": version: 5.2.1 resolution: "@bithighlander/bitcoin-cash-js-lib@npm:5.2.1" @@ -4191,13 +4138,6 @@ __metadata: languageName: node linkType: hard -"@brandonblack/musig@npm:^0.0.1-alpha.0": - version: 0.0.1-alpha.1 - resolution: "@brandonblack/musig@npm:0.0.1-alpha.1" - checksum: 3e116b30716481bf3d28d2a229bf9d93b3c6753f8c3d833c573db167656f135bfcb76d3c63a8c9c44d9cec6d6cafe56c420b4e647a9307ce69a31eb51ca11724 - languageName: node - linkType: hard - "@cetusprotocol/aggregator-sdk@npm:^1.4.2": version: 1.4.2 resolution: "@cetusprotocol/aggregator-sdk@npm:1.4.2" @@ -9314,6 +9254,15 @@ __metadata: languageName: node linkType: hard +"@noble/curves@npm:~1.7.0": + version: 1.7.0 + resolution: "@noble/curves@npm:1.7.0" + dependencies: + "@noble/hashes": 1.6.0 + checksum: e220b704f1e516f326fff985e794e840a267f5542e1388737142b08177672ebc41b460b5a5bf636d7622c68e8ae719bc042ccd8aed16dc14311450a94b5f2a05 + languageName: node + linkType: hard + "@noble/ed25519@npm:^1.6.0, @noble/ed25519@npm:^1.6.1, @noble/ed25519@npm:^1.7.1": version: 1.7.3 resolution: "@noble/ed25519@npm:1.7.3" @@ -9356,6 +9305,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:1.6.0": + version: 1.6.0 + resolution: "@noble/hashes@npm:1.6.0" + checksum: 07729b80108d2a9b862eb4e070d4f78ca7ee86b9a9c13a4f7c338ba47a15d4386dd283235da71f21ad515fa9f0b9429fc3da39d2f2b4a50e2442212d14cfd4a9 + languageName: node + linkType: hard + "@noble/hashes@npm:1.7.0": version: 1.7.0 resolution: "@noble/hashes@npm:1.7.0" @@ -9391,7 +9347,7 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:^1.1.5, @noble/hashes@npm:^1.2.0": +"@noble/hashes@npm:^1.1.5, @noble/hashes@npm:^1.2.0, @noble/hashes@npm:~1.6.0": version: 1.6.1 resolution: "@noble/hashes@npm:1.6.1" checksum: 57c62f65ee217c0293b4321b547792aa6d79812bfe70a7d62dc83e0f936cc677b14ed981b4e88cf8fdad37cd6d3a0cbd3bd0908b0728adc9daf066e678be8901 @@ -9405,13 +9361,6 @@ __metadata: languageName: node linkType: hard -"@noble/secp256k1@npm:1.6.3": - version: 1.6.3 - resolution: "@noble/secp256k1@npm:1.6.3" - checksum: 16eb3242533e645deb64444c771515f66bdc2ee0759894efd42fdeed4ab226ed29827aaaf6caa27d3d95b831452fd4246aa1007cd688aa462ad48fc084ab76e6 - languageName: node - linkType: hard - "@noble/secp256k1@npm:^1.5.5, @noble/secp256k1@npm:^1.7.1": version: 1.7.1 resolution: "@noble/secp256k1@npm:1.7.1" @@ -10813,7 +10762,7 @@ __metadata: languageName: node linkType: hard -"@scure/base@npm:1.2.6, @scure/base@npm:^1.2.6": +"@scure/base@npm:1.2.6, @scure/base@npm:^1.2.6, @scure/base@npm:~1.2.1": version: 1.2.6 resolution: "@scure/base@npm:1.2.6" checksum: 1058cb26d5e4c1c46c9cc0ae0b67cc66d306733baf35d6ebdd8ddaba242b80c3807b726e3b48cb0411bb95ec10d37764969063ea62188f86ae9315df8ea6b325 @@ -10953,6 +10902,26 @@ __metadata: languageName: node linkType: hard +"@scure/starknet@npm:1.1.0": + version: 1.1.0 + resolution: "@scure/starknet@npm:1.1.0" + dependencies: + "@noble/curves": ~1.7.0 + "@noble/hashes": ~1.6.0 + checksum: 7aa08f272c16e2ad6ef6d79e8d8e133fa56876a1e1dd276e9103bc7f6ac2bcff1974594be7e56b08203dbaed1b40353c1633b5673cd349969bb1769e6f0be8a0 + languageName: node + linkType: hard + +"@scure/starknet@npm:^1.0.0": + version: 1.1.2 + resolution: "@scure/starknet@npm:1.1.2" + dependencies: + "@noble/curves": ~1.9.0 + "@noble/hashes": ~1.8.0 + checksum: 54479d5b2f4768821a0813607f32863d375a82b8b0e3317b7bb31e8fe8a12d378bd3f3b7100c81a2db273e5c0485d807a61026c4acb067407bd51b1737ecbf97 + languageName: node + linkType: hard + "@sentry-internal/browser-utils@npm:8.26.0, @sentry-internal/browser-utils@npm:^8.26.0": version: 8.26.0 resolution: "@sentry-internal/browser-utils@npm:8.26.0" @@ -11165,8 +11134,8 @@ __metadata: dependencies: "@mysten/sui": 1.45.0 "@shapeshiftoss/caip": "workspace:^" - "@shapeshiftoss/hdwallet-core": 1.62.32 - "@shapeshiftoss/hdwallet-ledger": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 + "@shapeshiftoss/hdwallet-ledger": 1.62.35 "@shapeshiftoss/types": "workspace:^" "@shapeshiftoss/unchained-client": "workspace:^" "@shapeshiftoss/utils": "workspace:^" @@ -11229,15 +11198,15 @@ __metadata: languageName: unknown linkType: soft -"@shapeshiftoss/hdwallet-coinbase@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-coinbase@npm:1.62.32" +"@shapeshiftoss/hdwallet-coinbase@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-coinbase@npm:1.62.35" dependencies: "@coinbase/wallet-sdk": ^3.6.6 - "@shapeshiftoss/hdwallet-core": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 eth-rpc-errors: ^4.0.3 lodash: ^4.17.21 - checksum: 95283510771bc0f616439dfeb7522daa951e28cefa9f406257d96dd81c06bb152d7f180ee55d0307748c6c7da3e3bf6f0fe839c8b9f7c3e56cdf518178e035cd + checksum: 5a07ad7dda759406f6850084235eae8fc105a96e8946ebd1bc2d8f805b21dea1a17208a95ab8515ea795d6ba000e24b6109c3691aca333e910ab7c46cf4bd9db languageName: node linkType: hard @@ -11259,9 +11228,9 @@ __metadata: languageName: node linkType: hard -"@shapeshiftoss/hdwallet-core@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-core@npm:1.62.32" +"@shapeshiftoss/hdwallet-core@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-core@npm:1.62.35" dependencies: "@shapeshiftoss/bitcoinjs-lib": 7.0.0-shapeshift.2 "@shapeshiftoss/proto-tx-builder": 0.10.0 @@ -11273,7 +11242,7 @@ __metadata: lodash: ^4.17.21 rxjs: ^6.4.0 type-assertions: ^1.1.0 - checksum: a2c2eb6da5f2e57ecefcd503580ce5315f77421ba727ee86dec5484812ed4fb42aff8a11b674b7f8d2279af1f7838b3a7594a8a4abb7ddf0efe149f910332dad + checksum: f1fd814b8ee5b02575445d3a012afc6e3493ff22762fc4ddba2904a516133d236a9e705f14be676faa1a2d305435e9f6ef7f22d41f0765bc81c76ead1347bf29 languageName: node linkType: hard @@ -11295,39 +11264,39 @@ __metadata: languageName: node linkType: hard -"@shapeshiftoss/hdwallet-gridplus@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-gridplus@npm:1.62.32" +"@shapeshiftoss/hdwallet-gridplus@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-gridplus@npm:1.62.35" dependencies: "@bitcoinerlab/secp256k1": ^1.1.1 "@ethereumjs/common": 4.4.0 "@ethereumjs/rlp": 5.0.2 "@ethereumjs/tx": 5.4.0 "@metamask/eth-sig-util": ^7.0.0 - "@shapeshiftoss/hdwallet-core": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 bech32: ^1.1.4 bs58: ^5.0.0 bs58check: ^4.0.0 crypto-js: ^4.2.0 gridplus-sdk: ^3.2.0 lodash: ^4.17.21 - checksum: cd00b9bad19db54261422d8486b96a530770e793e0676816a742e2ae2a196743f965bd7aceb0982c6a6d3a51e7b8fda402e0427e46b95248be881e984b5cf21e + checksum: 254083d319ef3d670665264dbe10544f23988e96cb56e98690d988375bd5fa791444ac662ae133fe373815499b236541b3dfcb118bdd291f943a79c586e84558 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-keepkey-webusb@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-keepkey-webusb@npm:1.62.32" +"@shapeshiftoss/hdwallet-keepkey-webusb@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-keepkey-webusb@npm:1.62.35" dependencies: - "@shapeshiftoss/hdwallet-core": 1.62.32 - "@shapeshiftoss/hdwallet-keepkey": 1.62.32 - checksum: 3eac35d649529a4029ec18ee05372d901111961bf31d246b9a020a9f53b3706def030b4ef928e5c21efad91e8ff288c9420fc0a9b975e750c343196459f6678c + "@shapeshiftoss/hdwallet-core": 1.62.35 + "@shapeshiftoss/hdwallet-keepkey": 1.62.35 + checksum: 4cf1be6a1498bb2f44e7acf43725754ee0030e619539785e639367e1756be5ff7ef4002a38d06b8d2373102005507501b7cf0feaeb8c88d52d8b6dceef52f9f3 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-keepkey@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-keepkey@npm:1.62.32" +"@shapeshiftoss/hdwallet-keepkey@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-keepkey@npm:1.62.35" dependencies: "@bitcoinerlab/secp256k1": ^1.1.1 "@ethereumjs/common": 3.2.0 @@ -11335,7 +11304,7 @@ __metadata: "@keepkey/device-protocol": 7.13.4 "@metamask/eth-sig-util": ^7.0.0 "@shapeshiftoss/bitcoinjs-lib": 7.0.0-shapeshift.2 - "@shapeshiftoss/hdwallet-core": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 "@shapeshiftoss/proto-tx-builder": 0.10.0 bignumber.js: ^9.0.1 bnb-javascript-sdk-nobroadcast: 2.16.15 @@ -11348,44 +11317,44 @@ __metadata: lodash: ^4.17.21 p-lazy: ^3.1.0 semver: ^7.3.8 - checksum: 5d202e4c852eb6fad05eed81a7ee7da81749ba62a603fabf85b61c875efeda62dadc56ce01f9fdb5b9fd8bb86940c78c101f42aff1d74cfe8f52931efcaa5d9c + checksum: ccc726259d3701262a9cbcced8327f379bee1a300146e2b1f88e83052223e035e476377f801a4dcb3478bc268b5c3350a1c32ebd4a44b4746f98e2716e984ad5 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-keplr@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-keplr@npm:1.62.32" +"@shapeshiftoss/hdwallet-keplr@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-keplr@npm:1.62.35" dependencies: "@cosmjs/amino": ^0.28.13 "@cosmjs/stargate": ^0.28.13 "@shapeshiftoss/caip": 8.15.0 - "@shapeshiftoss/hdwallet-core": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 "@shapeshiftoss/proto-tx-builder": 0.10.0 "@shapeshiftoss/types": 3.1.3 base64-js: ^1.5.1 lodash: ^4.17.21 - checksum: 064234f2eab9641fe2b4ef1e73669e27cbc48d03214c7594c148140c654809833a53f1c5a5c416fc18ad020f15f48a5dfc100b5492cd9dbdda7e17ad296d7c7b + checksum: bdd2e213acab343668c2faa30bca271502135f478e2adfa292c31ae79d1eedba6b95ed7f82bd691fb9470acab38efda95b62e049c7427b34cd7fc47e82071b9d languageName: node linkType: hard -"@shapeshiftoss/hdwallet-ledger-webhid@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-ledger-webhid@npm:1.62.32" +"@shapeshiftoss/hdwallet-ledger-webhid@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-ledger-webhid@npm:1.62.35" dependencies: "@ledgerhq/hw-app-btc": 10.13.0 "@ledgerhq/hw-app-eth": 7.0.0 "@ledgerhq/hw-transport": 6.31.13 "@ledgerhq/hw-transport-webhid": 6.30.6 - "@shapeshiftoss/hdwallet-core": 1.62.32 - "@shapeshiftoss/hdwallet-ledger": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 + "@shapeshiftoss/hdwallet-ledger": 1.62.35 "@types/w3c-web-hid": ^1.0.2 - checksum: 21924ef52eabb07603106f4094f123b38887d187f312d642bd0fe933acbf9ab98fc40cc5c45a99ecbf7fc3c2f671ac25c74bb684ca831e81e3bd342926abce26 + checksum: a978efaf834cca764f0da249b7ec66f5b3e8c65540cd1669af15aa4e34391467076130f253978854112e18f4f35876a4e3b6026e55340b87e707c45092899d28 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-ledger-webusb@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-ledger-webusb@npm:1.62.32" +"@shapeshiftoss/hdwallet-ledger-webusb@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-ledger-webusb@npm:1.62.35" dependencies: "@ledgerhq/hw-app-btc": 10.13.0 "@ledgerhq/hw-app-cosmos": 6.32.9 @@ -11393,19 +11362,18 @@ __metadata: "@ledgerhq/hw-app-solana": 7.6.0 "@ledgerhq/hw-transport": 6.31.13 "@ledgerhq/hw-transport-webusb": 6.29.13 - "@shapeshiftoss/hdwallet-core": 1.62.32 - "@shapeshiftoss/hdwallet-ledger": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 + "@shapeshiftoss/hdwallet-ledger": 1.62.35 "@types/w3c-web-usb": ^1.0.4 p-queue: ^7.4.1 - checksum: 6f92b5be4edab9bf42aa2500ff6d17ab9019c8cf18de723161f64300e9763b87d689893112c78a714635a32d45814f404c1d95317cb339d326d59e62c9869232 + checksum: 1a787c0f701888e10322df3580b5832eb21d06c69cdf5521ee750b8a46e4916f5923243ac367dd96f05bbbfb15a9037e159196fee8e38928ce83931eaf40e8f4 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-ledger@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-ledger@npm:1.62.32" +"@shapeshiftoss/hdwallet-ledger@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-ledger@npm:1.62.35" dependencies: - "@bitgo/utxo-lib": ^11.18.0 "@ethereumjs/common": 3.2.0 "@ethereumjs/tx": 4.2.0 "@ledgerhq/device-core": 0.6.9 @@ -11418,7 +11386,7 @@ __metadata: "@ledgerhq/logs": 6.13.0 "@mysten/ledgerjs-hw-app-sui": ^0.7.0 "@shapeshiftoss/bitcoinjs-lib": 7.0.0-shapeshift.2 - "@shapeshiftoss/hdwallet-core": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 "@solana/web3.js": 1.95.8 base64-js: ^1.5.1 bchaddrjs: ^0.4.4 @@ -11428,33 +11396,33 @@ __metadata: ethereumjs-util: ^6.1.0 ethers: 5.7.2 lodash: ^4.17.21 - checksum: da68c61c47d20bd43ac747e7ca132002d32ad7a46055ea3e6ba612cdf202c209bc3f1f5879719caa4ec999a55161ccd48b07d191b059d7a0b303071f8de3c4bb + checksum: b860f661eb728bb091274d40fcd7f444255e1a1a62ae53e8cfc7cbfd2429bf01a8d7089b2c35d4c1fac11805c63ddc200994bc2deb2109c15b36107b7b8f650c languageName: node linkType: hard -"@shapeshiftoss/hdwallet-metamask-multichain@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-metamask-multichain@npm:1.62.32" +"@shapeshiftoss/hdwallet-metamask-multichain@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-metamask-multichain@npm:1.62.35" dependencies: "@metamask/detect-provider": ^1.2.0 "@metamask/onboarding": ^1.0.1 "@shapeshiftoss/common-api": ^9.3.0 - "@shapeshiftoss/hdwallet-core": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 "@shapeshiftoss/metamask-snaps-adapter": ^1.0.12 "@shapeshiftoss/metamask-snaps-types": ^1.0.12 eth-rpc-errors: ^4.0.3 lodash: ^4.17.21 mipd: ^0.0.7 - checksum: c588351427f537dd931dd71f837655f1122b7512df1674e2d3a005fc2bb272fbe20088a0020991b384adf6d151d1d978a736ddbe662c37043df546aedc20d435 + checksum: f7efc21fea5c77ceb711e17ca4afa92840df5c3c7cbe8f47c512a6067a151fd8b4f76606821b1b9d319e354db9b4bc5c4f58b7f5d94a639f1550543d68599002 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-native-vault@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-native-vault@npm:1.62.32" +"@shapeshiftoss/hdwallet-native-vault@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-native-vault@npm:1.62.35" dependencies: "@bitcoinerlab/secp256k1": ^1.1.1 - "@shapeshiftoss/hdwallet-native": 1.62.32 + "@shapeshiftoss/hdwallet-native": 1.62.35 bip39: ^3.0.4 hash-wasm: ^4.11.0 idb-keyval: ^6.0.3 @@ -11462,18 +11430,19 @@ __metadata: p-lazy: ^3.1.0 type-assertions: ^1.1.0 uuid: ^8.3.2 - checksum: 558575ed283bfe3718e4dc6251e6d82d74aa05095a33d88f74f0d843c876c478ff54317f6f37778b73b74c6664f8cafcb8449857f87f8664139cb78391ed7dad + checksum: 83b29173bf7c469e7d8f70567b555136c2172432f32f7f39d53935ca45b68e7c57a39954a4b942aa9f7ef4afec4ffc62e5436421862a27da446e9880fe30af3c languageName: node linkType: hard -"@shapeshiftoss/hdwallet-native@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-native@npm:1.62.32" +"@shapeshiftoss/hdwallet-native@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-native@npm:1.62.35" dependencies: "@bitcoinerlab/secp256k1": ^1.1.1 "@noble/curves": ^1.4.0 + "@scure/starknet": ^1.0.0 "@shapeshiftoss/bitcoinjs-lib": 7.0.0-shapeshift.2 - "@shapeshiftoss/hdwallet-core": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 "@shapeshiftoss/proto-tx-builder": 0.10.0 "@zxing/text-encoding": ^0.9.0 bchaddrjs: ^0.4.9 @@ -11494,8 +11463,9 @@ __metadata: node-fetch: ^2.6.1 p-lazy: ^3.1.0 scrypt-js: ^3.0.1 + starknet: ^9.3.0 tendermint-tx-builder: 1.0.16 - checksum: ef16b0c334ec3a5fe90962113391e1c816b42a1751ea733ace4eb3095eeaf19fbfd9e2c71f7179243ce18b1286afdd0a9ee98ba5aff7a04af387cc5b831fdab8 + checksum: b8ed640bc0b9c850ad5cd30a8f865e156fd9bba20bd18b238fa17511d686eb77bc3006ec790f555edb4ed8b312b8e7a26ddd71e96636f1903e3f38cd91158170 languageName: node linkType: hard @@ -11532,84 +11502,84 @@ __metadata: languageName: node linkType: hard -"@shapeshiftoss/hdwallet-phantom@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-phantom@npm:1.62.32" +"@shapeshiftoss/hdwallet-phantom@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-phantom@npm:1.62.35" dependencies: "@shapeshiftoss/bitcoinjs-lib": 7.0.0-shapeshift.2 - "@shapeshiftoss/hdwallet-core": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 "@solana/web3.js": 1.95.8 base64-js: ^1.5.1 bitcoinjs-message: ^2.0.0 ethers: 5.7.2 lodash: ^4.17.21 - checksum: 226333783bd05e670e5771fed795341ac4d2eb2caba4c90ebd8d7f76c719dae27ce2750b4aa5cb0a4e11e656e6f6de0aaacabd15680fceb15d9dff1861465d7e + checksum: bf2ca9954b22e89c560f3e9bdf3ab22619cf5c8ae7ee52982bf39974ae6c41ee420466b60ae17de6f79a6d0a4370e6099c1338c102ffbf84d0c685bb90abf54a languageName: node linkType: hard -"@shapeshiftoss/hdwallet-trezor-connect@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-trezor-connect@npm:1.62.32" +"@shapeshiftoss/hdwallet-trezor-connect@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-trezor-connect@npm:1.62.35" dependencies: - "@shapeshiftoss/hdwallet-core": 1.62.32 - "@shapeshiftoss/hdwallet-trezor": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 + "@shapeshiftoss/hdwallet-trezor": 1.62.35 "@trezor/connect-web": ^9.6.4 - checksum: a28d5d50363c879bba396ebb523f28784f377f1d7236621778156418e53504a1c506cb1ec6c7b82351922ebad867c21ad772ec4535c0f0f5c7fa3b05d70878a1 + checksum: 6c267da47b051e77226181c8f7cea365db05ed6d43099da8cb343ab0276e4125fac241c072d6e2bf521739f1b2de54e8fd45f5049d230322465d0fffe40bfe8e languageName: node linkType: hard -"@shapeshiftoss/hdwallet-trezor@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-trezor@npm:1.62.32" +"@shapeshiftoss/hdwallet-trezor@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-trezor@npm:1.62.35" dependencies: "@ethereumjs/common": 3.2.0 "@ethereumjs/tx": 4.2.0 - "@shapeshiftoss/hdwallet-core": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 base64-js: ^1.5.1 bchaddrjs: ^0.4.4 lodash: ^4.17.21 - checksum: 0a406408758e37d45f1b4f976993fcdcae4feb520b1d866c8455d3a9abd72a14955592dc8a184553cd3fa4441383c577d610bdc7e138bef2ec3be57b2d4b8b28 + checksum: dca5d30e6884c3fcd422ebc6a8c9fec0a452757e69c96b70738741d2b625c25b3e4dcb244032ab862627cdb3c0cda097b8c8653f757f9a36ba6f6ae19abd6919 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-vultisig@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-vultisig@npm:1.62.32" +"@shapeshiftoss/hdwallet-vultisig@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-vultisig@npm:1.62.35" dependencies: "@cosmjs/amino": ^0.28.13 "@cosmjs/stargate": ^0.28.13 "@shapeshiftoss/bitcoinjs-lib": 7.0.0-shapeshift.2 - "@shapeshiftoss/hdwallet-core": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 "@solana/web3.js": 1.95.8 base64-js: ^1.5.1 bitcoinjs-message: ^2.0.0 ethers: 5.7.2 lodash: ^4.17.21 - checksum: b998687a68fba0ef53a032e5796bd326542745fa5a414def16dad1f03329f75819fda2d1b375d86b5546443998fd66979c5e66e04a10e1fac3675d70fbcb5ab3 + checksum: 848dffb99db0d53bf26465dcf67326e0f78eab2e8aa844b5c75616742e3cd5dd7f5a23b41e0fa4999d10a49557c84bc73149a2b566c04004d9d8edf1afb522eb languageName: node linkType: hard -"@shapeshiftoss/hdwallet-walletconnect@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-walletconnect@npm:1.62.32" +"@shapeshiftoss/hdwallet-walletconnect@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-walletconnect@npm:1.62.35" dependencies: - "@shapeshiftoss/hdwallet-core": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 "@walletconnect/qrcode-modal": ^1.7.8 "@walletconnect/web3-provider": ^1.7.8 ethers: ^5.6.5 - checksum: 6c396da7342c878e3c3a291892d3bd203c2ab1340e3e9a941c9d729e6d1397788b24aaef89a6b8e1c678e6d3498d57d8a8e344e45f487cfac8ed8baf055e56aa + checksum: 6561ddaf693ded9132153a99726992dcaf963d2d6a01f78444b87399cdc11f04d0e57484fbc90b544e1301109a57d38f276ea3869c8105489df9329296686313 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-walletconnectv2@npm:1.62.32": - version: 1.62.32 - resolution: "@shapeshiftoss/hdwallet-walletconnectv2@npm:1.62.32" +"@shapeshiftoss/hdwallet-walletconnectv2@npm:1.62.35": + version: 1.62.35 + resolution: "@shapeshiftoss/hdwallet-walletconnectv2@npm:1.62.35" dependencies: - "@shapeshiftoss/hdwallet-core": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 "@walletconnect/ethereum-provider": ^2.20.2 "@walletconnect/modal": ^2.6.2 ethers: ^5.6.5 - checksum: 829fad90f9bf9aaa0a4da80e87b6db3d6fd3337fbc07c54177912cd9eb6b03274d1bde41c67756a9ae81bae186fbf1990ffb61de273c0902bf02ae3999d03c43 + checksum: 8cbb6ddd5983ab4f8f824218c83cae43f5aa5816a5f65f69de199267f7963ddd0a0fadfdb8685b5a00f34d2af361aee67528051bc69459bfccfe8db6480e4811 languageName: node linkType: hard @@ -11719,7 +11689,7 @@ __metadata: "@shapeshiftoss/caip": "workspace:^" "@shapeshiftoss/chain-adapters": "workspace:^" "@shapeshiftoss/contracts": "workspace:^" - "@shapeshiftoss/hdwallet-core": 1.62.32 + "@shapeshiftoss/hdwallet-core": 1.62.35 "@shapeshiftoss/types": "workspace:^" "@shapeshiftoss/unchained-client": "workspace:^" "@shapeshiftoss/utils": "workspace:^" @@ -11854,24 +11824,24 @@ __metadata: "@shapeshiftoss/chain-adapters": "workspace:^" "@shapeshiftoss/contracts": "workspace:^" "@shapeshiftoss/errors": "workspace:^" - "@shapeshiftoss/hdwallet-coinbase": 1.62.32 - "@shapeshiftoss/hdwallet-core": 1.62.32 - "@shapeshiftoss/hdwallet-gridplus": 1.62.32 - "@shapeshiftoss/hdwallet-keepkey": 1.62.32 - "@shapeshiftoss/hdwallet-keepkey-webusb": 1.62.32 - "@shapeshiftoss/hdwallet-keplr": 1.62.32 - "@shapeshiftoss/hdwallet-ledger": 1.62.32 - "@shapeshiftoss/hdwallet-ledger-webhid": 1.62.32 - "@shapeshiftoss/hdwallet-ledger-webusb": 1.62.32 - "@shapeshiftoss/hdwallet-metamask-multichain": 1.62.32 - "@shapeshiftoss/hdwallet-native": 1.62.32 - "@shapeshiftoss/hdwallet-native-vault": 1.62.32 - "@shapeshiftoss/hdwallet-phantom": 1.62.32 - "@shapeshiftoss/hdwallet-trezor": 1.62.32 - "@shapeshiftoss/hdwallet-trezor-connect": 1.62.32 - "@shapeshiftoss/hdwallet-vultisig": 1.62.32 - "@shapeshiftoss/hdwallet-walletconnect": 1.62.32 - "@shapeshiftoss/hdwallet-walletconnectv2": 1.62.32 + "@shapeshiftoss/hdwallet-coinbase": 1.62.35 + "@shapeshiftoss/hdwallet-core": 1.62.35 + "@shapeshiftoss/hdwallet-gridplus": 1.62.35 + "@shapeshiftoss/hdwallet-keepkey": 1.62.35 + "@shapeshiftoss/hdwallet-keepkey-webusb": 1.62.35 + "@shapeshiftoss/hdwallet-keplr": 1.62.35 + "@shapeshiftoss/hdwallet-ledger": 1.62.35 + "@shapeshiftoss/hdwallet-ledger-webhid": 1.62.35 + "@shapeshiftoss/hdwallet-ledger-webusb": 1.62.35 + "@shapeshiftoss/hdwallet-metamask-multichain": 1.62.35 + "@shapeshiftoss/hdwallet-native": 1.62.35 + "@shapeshiftoss/hdwallet-native-vault": 1.62.35 + "@shapeshiftoss/hdwallet-phantom": 1.62.35 + "@shapeshiftoss/hdwallet-trezor": 1.62.35 + "@shapeshiftoss/hdwallet-trezor-connect": 1.62.35 + "@shapeshiftoss/hdwallet-vultisig": 1.62.35 + "@shapeshiftoss/hdwallet-walletconnect": 1.62.35 + "@shapeshiftoss/hdwallet-walletconnectv2": 1.62.35 "@shapeshiftoss/swapper": "workspace:^" "@shapeshiftoss/types": "workspace:^" "@shapeshiftoss/unchained-client": "workspace:^" @@ -13180,6 +13150,39 @@ __metadata: languageName: node linkType: hard +"@starknet-io/get-starknet-wallet-standard@npm:^5.0.0": + version: 5.0.0 + resolution: "@starknet-io/get-starknet-wallet-standard@npm:5.0.0" + dependencies: + "@starknet-io/types-js": ^0.7.10 + "@wallet-standard/base": ^1.1.0 + "@wallet-standard/features": ^1.1.0 + ox: ^0.4.4 + checksum: 41c9327d98c37054da83fa1a36a38f850a4d3dc9d10f29106b60948063e37c30e37b1761d957901c453cdc559f2a2c9a208b9032f5b702155da41a7a3e326148 + languageName: node + linkType: hard + +"@starknet-io/starknet-types-010@npm:@starknet-io/types-js@0.10.0": + version: 0.10.0 + resolution: "@starknet-io/types-js@npm:0.10.0" + checksum: 5f07bd2836653b6d8e30646332fe6e79b57157b252db929ff790ef4387ddb8ee3300cc5a64efc26bc4c4a45decd1ac309e20959c06f0ab6e7a2eeb0b3238788a + languageName: node + linkType: hard + +"@starknet-io/starknet-types-09@npm:@starknet-io/types-js@~0.9.1": + version: 0.9.2 + resolution: "@starknet-io/types-js@npm:0.9.2" + checksum: df504df0f69bee72975bf299424c2c61f14f9cd7982883124f7dd7f40f9ec58b53df9c010321ca6efb45dbc292b92cba948a175b49bdc4b77c20c059487681e9 + languageName: node + linkType: hard + +"@starknet-io/types-js@npm:^0.7.10": + version: 0.7.10 + resolution: "@starknet-io/types-js@npm:0.7.10" + checksum: 8f71c57d0f101ebbde91e3016b73ab70ce3329ccb7463764a27a61db42b9ea14b690bd620a6b2dd4303e890b4a9212bdd40626962e0320e82e0c600fd3be5abf + languageName: node + linkType: hard + "@stellar/js-xdr@npm:^3.1.2": version: 3.1.2 resolution: "@stellar/js-xdr@npm:3.1.2" @@ -15513,6 +15516,22 @@ __metadata: languageName: node linkType: hard +"@wallet-standard/base@npm:^1.1.0": + version: 1.1.0 + resolution: "@wallet-standard/base@npm:1.1.0" + checksum: 4057188f615f1deeb0c8a39f04018d4575f87cb387749dab6bc2e8232a95400be51ea4235450829bb256aa21136621f47167383ef1767f0eb3109f1140c74d86 + languageName: node + linkType: hard + +"@wallet-standard/features@npm:^1.1.0": + version: 1.1.0 + resolution: "@wallet-standard/features@npm:1.1.0" + dependencies: + "@wallet-standard/base": ^1.1.0 + checksum: c0c101ee0bd4c55619e39505d15158132bbd619f4dc611880a4b0c001e96806957bed35d7a51efdff0077cf5afb01e0dc46a32b01d9d8c27f807fc2b61e92159 + languageName: node + linkType: hard + "@walletconnect/browser-utils@npm:^1.8.0": version: 1.8.0 resolution: "@walletconnect/browser-utils@npm:1.8.0" @@ -16516,6 +16535,20 @@ __metadata: languageName: node linkType: hard +"abi-wan-kanabi@npm:2.2.4": + version: 2.2.4 + resolution: "abi-wan-kanabi@npm:2.2.4" + dependencies: + ansicolors: ^0.3.2 + cardinal: ^2.1.1 + fs-extra: ^10.0.0 + yargs: ^17.7.2 + bin: + generate: dist/generate.js + checksum: 6d7cbb424f6e7fda479aaa586e114bbbe0f65bea19215f8a8847b7ab67bdf07baff42ea07c9cfba0f8067f2503490a1017eb3c9fc92df79b8f94a87301f705d4 + languageName: node + linkType: hard + "abitype@npm:0.9.8": version: 0.9.8 resolution: "abitype@npm:0.9.8" @@ -16839,7 +16872,7 @@ __metadata: languageName: node linkType: hard -"ansicolors@npm:^0.3.2": +"ansicolors@npm:^0.3.2, ansicolors@npm:~0.3.2": version: 0.3.2 resolution: "ansicolors@npm:0.3.2" checksum: e84fae7ebc27ac96d9dbb57f35f078cd6dde1b7046b0f03f73dcefc9fbb1f2e82e3685d083466aded8faf038f9fa9ebb408d215282bcd7aaa301d5ac3c486815 @@ -18018,13 +18051,6 @@ __metadata: languageName: node linkType: hard -"bip174@npm:@bitgo-forks/bip174@3.1.0-master.4": - version: 3.1.0-master.4 - resolution: "@bitgo-forks/bip174@npm:3.1.0-master.4" - checksum: 23d8c613cd04368698fa4e8e5bc146a006d5c8d88c24dbe5cddcf793e055d9d86544598bc8617b05a6b44954bc337bc193462d580846814df29f8e09d9cbc955 - languageName: node - linkType: hard - "bip174@npm:^2.0.1": version: 2.0.1 resolution: "bip174@npm:2.0.1" @@ -18083,20 +18109,6 @@ __metadata: languageName: node linkType: hard -"bip32@npm:^3.0.1": - version: 3.1.0 - resolution: "bip32@npm:3.1.0" - dependencies: - bs58check: ^2.1.1 - create-hash: ^1.2.0 - create-hmac: ^1.1.7 - ripemd160: ^2.0.2 - typeforce: ^1.11.5 - wif: ^2.0.6 - checksum: 55bdc5dcae6cf83c000262cee9df912fe3012eeb000ff7cff72547e52442b7a779e93e7a19affbaa105d22f8d95299f8964edb2912f11a2bdd7b31433a7b5bad - languageName: node - linkType: hard - "bip39-light@npm:^1.0.7": version: 1.0.7 resolution: "bip39-light@npm:1.0.7" @@ -18199,24 +18211,6 @@ __metadata: languageName: node linkType: hard -"bitcoinjs-lib@npm:@bitgo-forks/bitcoinjs-lib@7.1.0-master.11": - version: 7.1.0-master.11 - resolution: "@bitgo-forks/bitcoinjs-lib@npm:7.1.0-master.11" - dependencies: - bech32: ^2.0.0 - bip174: "npm:@bitgo-forks/bip174@3.1.0-master.4" - bs58check: ^2.1.2 - create-hash: ^1.1.0 - fastpriorityqueue: ^0.7.1 - json5: ^2.2.3 - ripemd160: ^2.0.2 - typeforce: ^1.11.3 - varuint-bitcoin: ^1.1.2 - wif: ^2.0.1 - checksum: f7760c687fe0705cd3bdd45431742fc871995ea451f669061196eb2b1a5500dcede841597e7a6f909b8ee0bbd42e284fd9a0ce997a1ca82c8e73d57300cfa359 - languageName: node - linkType: hard - "bitcoinjs-lib@npm:^5.0.3, bitcoinjs-lib@npm:^5.2.0": version: 5.2.0 resolution: "bitcoinjs-lib@npm:5.2.0" @@ -18993,6 +18987,18 @@ __metadata: languageName: node linkType: hard +"cardinal@npm:^2.1.1": + version: 2.1.1 + resolution: "cardinal@npm:2.1.1" + dependencies: + ansicolors: ~0.3.2 + redeyed: ~2.1.0 + bin: + cdl: ./bin/cdl.js + checksum: e8d4ae46439cf8fed481c0efd267711ee91e199aa7821a9143e784ed94a6495accd01a0b36d84d377e8ee2cc9928a6c9c123b03be761c60b805f2c026b8a99ad + languageName: node + linkType: hard + "caseless@npm:~0.12.0": version: 0.12.0 resolution: "caseless@npm:0.12.0" @@ -19000,15 +19006,6 @@ __metadata: languageName: node linkType: hard -"cashaddress@npm:^1.1.0": - version: 1.1.0 - resolution: "cashaddress@npm:1.1.0" - dependencies: - bigi: ^1.4.2 - checksum: 29d5c6e58502a6641cc9aba07822b328af5a26d9d1d8c3243cc13d1f06a781dbdbbff38d0ab0be46d9ca80664d7de7e0bfb782c6170a1a8b9574fb2b1cc42a9d - languageName: node - linkType: hard - "cashaddrjs@npm:0.4.4": version: 0.4.4 resolution: "cashaddrjs@npm:0.4.4" @@ -21076,17 +21073,6 @@ __metadata: languageName: node linkType: hard -"ecpair@npm:@bitgo/ecpair@2.1.0-rc.0": - version: 2.1.0-rc.0 - resolution: "@bitgo/ecpair@npm:2.1.0-rc.0" - dependencies: - randombytes: ^2.1.0 - typeforce: ^1.18.0 - wif: ^2.0.6 - checksum: 6884491e472ea1e2947f194363b723b88348487b8031512eb8657b9d6d58390586e66adf536707dd5950384442dab96ca059a7afc6f0d3cd975a1c66d0f6aa56 - languageName: node - linkType: hard - "ecpair@npm:^3.0.0-rc.0": version: 3.0.0-rc.0 resolution: "ecpair@npm:3.0.0-rc.0" @@ -23417,13 +23403,6 @@ __metadata: languageName: node linkType: hard -"fastpriorityqueue@npm:^0.7.1": - version: 0.7.5 - resolution: "fastpriorityqueue@npm:0.7.5" - checksum: 1a586d09814c2eebd2c29d85d503ecc016203843c8a93d95e0924a26809da2e35ea14e4ca2f4a138a52ec2faaee9077bb79939cfd0466f7cfcef40dcdd1ffe8a - languageName: node - linkType: hard - "fastq@npm:^1.6.0": version: 1.13.0 resolution: "fastq@npm:1.13.0" @@ -24651,18 +24630,6 @@ __metadata: languageName: node linkType: hard -"hash-base@npm:^3.1.2": - version: 3.1.2 - resolution: "hash-base@npm:3.1.2" - dependencies: - inherits: ^2.0.4 - readable-stream: ^2.3.8 - safe-buffer: ^5.2.1 - to-buffer: ^1.2.1 - checksum: ca7c548098ca2aa3616f8ddb0406c9cadd0fbc35868d885200692b13a3b6d5b30e2b55ab808ff6000c69f11b3c26fd98e5955b1484d79a59fbd07d1d6b65ca4b - languageName: node - linkType: hard - "hash-base@npm:~3.0, hash-base@npm:~3.0.4": version: 3.0.5 resolution: "hash-base@npm:3.0.5" @@ -27179,6 +27146,13 @@ __metadata: languageName: node linkType: hard +"lossless-json@npm:^4.2.0": + version: 4.3.0 + resolution: "lossless-json@npm:4.3.0" + checksum: 11d25eadd5abcd6e554cc4326e6f04ce18f99daae2b0811d559c02e81febda18fe27b816817c35f7725f2f148abb0399e50bef2ea9568be28c42cbc7d99624a6 + languageName: node + linkType: hard + "loupe@npm:^3.1.0, loupe@npm:^3.1.3": version: 3.1.3 resolution: "loupe@npm:3.1.3" @@ -28082,20 +28056,6 @@ __metadata: languageName: node linkType: hard -"nanoassert@npm:^1.0.0": - version: 1.1.0 - resolution: "nanoassert@npm:1.1.0" - checksum: f360fe639db8edc422de9f5a8a7d384ba9c11e9c6fac149f7ad3b0a94e4ec9d5aa44ce55b3e4c7682658efad792604fc96c336b0e80a3590744104ba58af80c7 - languageName: node - linkType: hard - -"nanoassert@npm:^2.0.0": - version: 2.0.0 - resolution: "nanoassert@npm:2.0.0" - checksum: b1d366f9524405f3337192d32dda6ac0b02374e4d0550c9aad33480caf2eb3c84c06f18f41f4c5404c14f6fc1ae6b84692b4375166dcb9f2d04a2ea9b9bccba0 - languageName: node - linkType: hard - "nanoid@npm:^3.1.31, nanoid@npm:^3.3.6": version: 3.3.6 resolution: "nanoid@npm:3.3.6" @@ -29037,6 +28997,26 @@ __metadata: languageName: node linkType: hard +"ox@npm:^0.4.4": + version: 0.4.4 + resolution: "ox@npm:0.4.4" + dependencies: + "@adraffy/ens-normalize": ^1.10.1 + "@noble/curves": ^1.6.0 + "@noble/hashes": ^1.5.0 + "@scure/bip32": ^1.5.0 + "@scure/bip39": ^1.4.0 + abitype: ^1.0.6 + eventemitter3: 5.0.1 + peerDependencies: + typescript: ">=5.4.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: 412f443924ca0400142b287afb97b688cc5fadab1f8ef3f1e586a970c696a39dfaf335444efc5fa85a76d322d35d7023ff5e0c8667cb9ba4a297244ebfacf23e + languageName: node + linkType: hard + "p-debounce@npm:^4.0.0": version: 4.0.0 resolution: "p-debounce@npm:4.0.0" @@ -29145,7 +29125,7 @@ __metadata: languageName: node linkType: hard -"pako@npm:^2.0.3": +"pako@npm:^2.0.3, pako@npm:^2.0.4": version: 2.1.0 resolution: "pako@npm:2.1.0" checksum: 71666548644c9a4d056bcaba849ca6fd7242c6cf1af0646d3346f3079a1c7f4a66ffec6f7369ee0dc88f61926c10d6ab05da3e1fca44b83551839e89edd75a3e @@ -30799,6 +30779,15 @@ pvutils@latest: languageName: node linkType: hard +"redeyed@npm:~2.1.0": + version: 2.1.1 + resolution: "redeyed@npm:2.1.1" + dependencies: + esprima: ~4.0.0 + checksum: 39a1426e377727cfb47a0e24e95c1cf78d969fbc388dc1e0fa1e2ef8a8756450cefb8b0c2598f63b85f1a331986fca7604c0db798427a5775a1dbdb9c1291979 + languageName: node + linkType: hard + "redis-errors@npm:^1.0.0, redis-errors@npm:^1.2.0": version: 1.2.0 resolution: "redis-errors@npm:1.2.0" @@ -31453,16 +31442,6 @@ pvutils@latest: languageName: node linkType: hard -"ripemd160@npm:^2.0.2": - version: 2.0.3 - resolution: "ripemd160@npm:2.0.3" - dependencies: - hash-base: ^3.1.2 - inherits: ^2.0.4 - checksum: da25591f15d3f03d3a26cabc8255634ee9e0ae89fc053846e6b3975bbdbae6941baeb539dba30e0aaec9a726c7442149de064e13c2510332e119e50beaf3314d - languageName: node - linkType: hard - "ripple-address-codec@npm:^5.0.0": version: 5.0.0 resolution: "ripple-address-codec@npm:5.0.0" @@ -32801,6 +32780,25 @@ pvutils@latest: languageName: node linkType: hard +"starknet@npm:^9.3.0": + version: 9.3.0 + resolution: "starknet@npm:9.3.0" + dependencies: + "@noble/curves": ~1.7.0 + "@noble/hashes": ~1.6.0 + "@scure/base": ~1.2.1 + "@scure/starknet": 1.1.0 + "@starknet-io/get-starknet-wallet-standard": ^5.0.0 + "@starknet-io/starknet-types-010": "npm:@starknet-io/types-js@0.10.0" + "@starknet-io/starknet-types-09": "npm:@starknet-io/types-js@~0.9.1" + abi-wan-kanabi: 2.2.4 + lossless-json: ^4.2.0 + pako: ^2.0.4 + ts-mixer: ^6.0.3 + checksum: 412451c3fca3d15bca1a90e7db8e16ebe0ee694574894c3a77f7a100993270739e8253bbdb4eef8c1b03bc6c13455c24452e5db6dcee862666948843e96ee602 + languageName: node + linkType: hard + "statuses@npm:>= 1.5.0 < 2": version: 1.5.0 resolution: "statuses@npm:1.5.0" @@ -33601,17 +33599,6 @@ pvutils@latest: languageName: node linkType: hard -"to-buffer@npm:^1.2.1": - version: 1.2.2 - resolution: "to-buffer@npm:1.2.2" - dependencies: - isarray: ^2.0.5 - safe-buffer: ^5.2.1 - typed-array-buffer: ^1.0.3 - checksum: b0cd2417989a9f3d47273301e8cec2c9798b19a117822424686f385f3ec0239d2defd5fd9f8e76cda0b21e2a2f5de65a58e806506bf4c296c31750c5efd3ae4b - languageName: node - linkType: hard - "to-fast-properties@npm:^2.0.0": version: 2.0.0 resolution: "to-fast-properties@npm:2.0.0" @@ -35072,7 +35059,7 @@ pvutils@latest: languageName: node linkType: hard -"varuint-bitcoin@npm:1.1.2, varuint-bitcoin@npm:^1.0.1, varuint-bitcoin@npm:^1.0.4, varuint-bitcoin@npm:^1.1.2": +"varuint-bitcoin@npm:1.1.2, varuint-bitcoin@npm:^1.0.1, varuint-bitcoin@npm:^1.0.4": version: 1.1.2 resolution: "varuint-bitcoin@npm:1.1.2" dependencies: @@ -36462,7 +36449,7 @@ pvutils@latest: languageName: node linkType: hard -"yargs@npm:^17.5.1": +"yargs@npm:^17.5.1, yargs@npm:^17.7.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: