UNPKG

@orderly.network/default-solana-adapter

Version:

1 lines 160 kB
{"version":3,"sources":["../src/version.ts","../src/walletAdapter.ts","../src/helper.ts","../src/constant.ts","../src/idl/solana_vault.ts","../src/solana.util.ts"],"sourcesContent":["\ndeclare global {\n interface Window {\n __ORDERLY_VERSION__?: {\n [key: string]: string;\n };\n }\n}\nif(typeof window !== 'undefined') {\n window.__ORDERLY_VERSION__ = window.__ORDERLY_VERSION__ || {};\n window.__ORDERLY_VERSION__[\"@orderly.network/default-solana-adapter\"] = \"2.5.3\";\n};\n\nexport default \"2.5.3\";\n","import { SolanaAdapterOption, SolanaWalletProvider } from \"./types\";\nimport {\n AddOrderlyKeyInputs,\n BaseWalletAdapter,\n Message,\n RegisterAccountInputs,\n SettleInputs,\n SignatureDomain,\n SimpleDI,\n WithdrawInputs,\n Account,\n MessageFactor,\n} from \"@orderly.network/core\";\nimport { API, MaxUint256, ChainNamespace } from \"@orderly.network/types\";\nimport * as ed from \"@noble/ed25519\";\nimport { encode as bs58encode, decode as bs58Decode } from \"bs58\";\nimport {\n addOrderlyKeyMessage,\n checkIsLedgerWallet,\n deposit,\n encodeLzMessage,\n getDepositQuoteFee,\n MsgType,\n registerAccountMessage,\n settleMessage,\n withdrawMessage,\n} from \"./helper\";\nimport { bytesToHex } from \"ethereum-cryptography/utils\";\nimport { getAccount } from \"@solana/spl-token\";\nimport { getUSDCAccounts } from \"./solana.util\";\nimport {\n clusterApiUrl,\n Connection,\n PublicKey,\n Transaction,\n TransactionInstruction,\n} from \"@solana/web3.js\";\nimport { WalletAdapterNetwork } from \"@solana/wallet-adapter-base\";\n\nclass DefaultSolanaWalletAdapter extends BaseWalletAdapter<SolanaAdapterOption> {\n chainNamespace: ChainNamespace = ChainNamespace.solana;\n\n private _address!: string;\n private _chainId!: number;\n private _provider!: SolanaWalletProvider;\n private _connection!: Connection;\n\n constructor() {\n super();\n }\n\n get address(): string {\n return this._address;\n }\n\n get chainId(): number {\n return this._chainId;\n }\n\n set chainId(chainId: number) {\n this._chainId = chainId;\n }\n\n get connection(): Connection {\n if (this._connection) {\n return this._connection;\n }\n if (this._provider.rpcUrl) {\n this._connection = new Connection(this._provider.rpcUrl, {\n commitment: \"confirmed\",\n });\n return this._connection;\n }\n if (this._provider.network === WalletAdapterNetwork.Devnet) {\n this._connection = new Connection(clusterApiUrl(this._provider.network), {\n commitment: \"confirmed\",\n });\n return this._connection;\n }\n\n\n const account = SimpleDI.get<Account>(\"account\");\n const url = '/v1/solana-rpc-proxy';\n this._connection = new Connection(`${account.apiBaseUrl}${url}`, {\n commitment: \"confirmed\",\n fetchMiddleware: async (info, init, fetch) => {\n \n const payload: MessageFactor = {\n url,\n method: init?.method as \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n data: JSON.parse(init?.body as string),\n }\n // console.log('payload', payload);\n const signature = await this.signMessageByOrderlyKey(payload);\n for (const key of Object.keys(signature)) {\n (init?.headers as any)[key] = signature[key as keyof typeof signature] as string;\n }\n return fetch(info, init);\n }\n });\n return this._connection;\n }\n\n private setConfig(config: SolanaAdapterOption) {\n this._address = config.address;\n this._chainId = config.chain.id;\n if (config.provider) {\n this._provider = config.provider;\n }\n }\n\n private lifecycleName(name: string, data: any) {\n console.log(\"lifecycle\", name, data);\n }\n\n active(config: SolanaAdapterOption): void {\n this.setConfig(config);\n this.lifecycleName(\"active\", config);\n }\n\n deactivate(): void {\n this.lifecycleName(\"deactivate\", {});\n }\n\n update(config: SolanaAdapterOption): void {\n this.lifecycleName(\"update\", config);\n this.setConfig(config);\n }\n\n generateSecretKey(): string {\n let privKey, secretKey;\n do {\n privKey = ed.utils.randomPrivateKey();\n secretKey = bs58encode(privKey);\n } while (secretKey.length !== 44);\n\n return secretKey;\n }\n\n uint8ArrayToHexString(uint8Array: Uint8Array): string {\n return Array.from(uint8Array)\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n async signMessage(message: Uint8Array): Promise<string> {\n const isLedger = checkIsLedgerWallet(this._address);\n // test ledger wallet\n // if (!isLedger) {\n // console.log(\"-- test error\");\n // throw new Error(\n // \"xxx Signing off chain messages with Ledger is not yet supported\"\n // );\n // }\n\n if (isLedger) {\n const transaction = new Transaction();\n\n transaction.add(\n new TransactionInstruction({\n keys: [],\n programId: new PublicKey(\n \"ComputeBudget111111111111111111111111111111\"\n ),\n data: new Uint8Array([3, 0, 0, 0, 0, 0, 0, 0, 0]) as any,\n })\n );\n\n transaction.add(\n new TransactionInstruction({\n keys: [],\n programId: new PublicKey(\n \"ComputeBudget111111111111111111111111111111\"\n ),\n data: new Uint8Array([2, 0, 0, 0, 0]) as any,\n })\n );\n\n transaction.add(\n new TransactionInstruction({\n keys: [],\n programId: new PublicKey(\n \"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr\"\n ),\n data: message as any,\n })\n );\n\n const userPublicKey = new PublicKey(this.address);\n\n transaction.feePayer = userPublicKey;\n\n const zeroHash = new Uint8Array(32).fill(0);\n transaction.recentBlockhash = new PublicKey(zeroHash).toString();\n\n\n const signedTransaction = await this._provider.signTransaction(\n transaction\n );\n\n\n const signature = signedTransaction.signatures[0].signature;\n if (signature) {\n return this.uint8ArrayToHexString(signature as any);\n } else {\n console.log(\"-- sign message error\", signature);\n throw new Error(\"Unsupported signature\");\n }\n }\n const signRes = await this._provider.signMessage(message);\n return \"0x\" + bytesToHex(signRes);\n }\n\n async generateRegisterAccountMessage(\n inputs: RegisterAccountInputs\n ): Promise<Message> {\n const [message, toSignatureMessage] = registerAccountMessage({\n ...inputs,\n chainId: this.chainId,\n });\n\n const signature = await this.signMessage(toSignatureMessage as Uint8Array);\n\n return {\n message: {\n ...message,\n chainType: \"SOL\",\n },\n signatured: signature,\n };\n }\n\n async generateWithdrawMessage(\n inputs: WithdrawInputs\n ): Promise<Message & { domain: SignatureDomain }> {\n const [message, toSignatureMessage] = withdrawMessage({\n ...inputs,\n chainId: this.chainId,\n });\n const signature = await this.signMessage(toSignatureMessage as Uint8Array);\n\n\n return {\n message: {\n ...message,\n chainType: \"SOL\",\n },\n domain: {\n name: \"\",\n version: \"\",\n chainId: this.chainId,\n verifyingContract: inputs.verifyContract!,\n },\n signatured: signature,\n };\n }\n\n async generateAddOrderlyKeyMessage(\n inputs: AddOrderlyKeyInputs\n ): Promise<Message> {\n const [message, toSignatureMessage] = addOrderlyKeyMessage({\n ...inputs,\n chainId: this.chainId,\n });\n const signature = await this.signMessage(toSignatureMessage as Uint8Array);\n\n return {\n message: {\n ...message,\n chainType: \"SOL\",\n },\n signatured: signature,\n };\n }\n\n async generateSettleMessage(\n inputs: SettleInputs\n ): Promise<Message & { domain: SignatureDomain }> {\n const [message, toSignatureMessage] = settleMessage({\n ...inputs,\n chainId: this.chainId,\n });\n const signature = await this.signMessage(toSignatureMessage as Uint8Array);\n return {\n message: {\n ...message,\n chainType: \"SOL\",\n },\n domain: {\n name: \"\",\n version: \"\",\n chainId: this.chainId,\n verifyingContract: inputs.verifyContract!,\n },\n signatured: signature,\n };\n }\n\n async getBalance(): Promise<bigint> {\n return BigInt(0);\n }\n\n async call(\n address: string,\n method: string,\n params: any[],\n options?: {\n abi: any;\n }\n ) {\n // console.log('-- solanan call', {\n // address,\n // method,\n // params,\n // options,\n // })\n if (method === \"balanceOf\") {\n const usdcPublicKey = new PublicKey(address);\n const userPublicKey = new PublicKey(this._address);\n const userUSDCAccount = getUSDCAccounts(usdcPublicKey, userPublicKey);\n const connection = this.connection;\n\n const usdcamount = await getAccount(\n connection,\n userUSDCAccount,\n \"confirmed\"\n );\n return usdcamount.amount;\n }\n if (method === \"allowance\") {\n return MaxUint256;\n }\n return BigInt(0);\n }\n\n async sendTransaction(\n contractAddress: string,\n method: string,\n payload: {\n from: string;\n to?: string;\n data: any[];\n value?: bigint;\n },\n options: {\n abi: any;\n }\n ) {\n console.log(\"-- solanan sendTransaction\", {\n contractAddress,\n method,\n payload,\n options,\n });\n if (method === \"deposit\") {\n return deposit({\n vaultAddress: contractAddress,\n userAddress: this._address,\n connection: this.connection,\n depositData: payload.data[0],\n sendTransaction: this._provider.sendTransaction,\n });\n }\n }\n\n async callOnChain(\n chain: API.NetworkInfos,\n address: string,\n method: string,\n params: any[],\n options: {\n abi: any;\n }\n ): Promise<any> {\n console.log(\"-- params \", {\n chain,\n address,\n method,\n params,\n });\n if (method === \"getDepositFee\") {\n return getDepositQuoteFee({\n vaultAddress: address,\n userAddress: this._address,\n connection: this.connection,\n depositData: params[1],\n });\n }\n return 0;\n }\n\n async pollTransactionReceiptWithBackoff(\n txHash: string,\n baseInterval?: number,\n maxInterval?: number,\n maxRetries?: number\n ): Promise<any> {\n return Promise.resolve({status: 1})\n }\n}\n\nexport { DefaultSolanaWalletAdapter };\n","import { BN, Program } from \"@coral-xyz/anchor\";\nimport type { WalletAdapterProps } from \"@solana/wallet-adapter-base\";\nimport {\n ComputeBudgetProgram,\n Connection,\n PublicKey,\n SystemProgram,\n TransactionMessage,\n VersionedTransaction,\n} from \"@solana/web3.js\";\nimport { decode as bs58Decode } from \"bs58\";\nimport { keccak256 } from \"ethereum-cryptography/keccak\";\nimport { bytesToHex, hexToBytes } from \"ethereum-cryptography/utils\";\nimport { AbiCoder, solidityPackedKeccak256 } from \"ethers\";\nimport {\n AddOrderlyKeyInputs,\n RegisterAccountInputs,\n type SettleInputs,\n type SignatureDomain,\n type WithdrawInputs,\n} from \"@orderly.network/core\";\nimport { LedgerWalletKey } from \"@orderly.network/types\";\nimport {\n DVN_PROGRAM_ID,\n ENDPOINT_PROGRAM_ID,\n EXECUTOR_PROGRAM_ID,\n PRICE_FEED_PROGRAM_ID,\n SEND_LIB_PROGRAM_ID,\n TREASURY_PROGRAM_ID,\n} from \"./constant\";\nimport { IDL as VaultIDL, SolanaVault } from \"./idl/solana_vault\";\nimport {\n getBrokerPDA,\n getDefaultSendConfigPda,\n getDefaultSendLibConfigPda,\n getDstEID,\n getDvnConfigPda,\n getEndorcedOptionsPda,\n getEndpointSettingPda,\n getEventAuthorityPda,\n getExecutorConfigPda,\n getLookupTableAccount,\n getLookupTableAddress,\n getMessageLibInfoPda,\n getMessageLibPda,\n getNoncePda,\n getOAppConfigPda,\n getPeerAddress,\n getPeerPda,\n getPriceFeedPda,\n getSendConfigPda,\n getSendLibConfigPda,\n getSendLibInfoPda,\n getSendLibPda,\n getTokenPDA,\n getUlnEventAuthorityPda,\n getUlnSettingPda,\n getUSDCAccounts,\n getVaultAuthorityPda,\n} from \"./solana.util\";\n\nexport function addOrderlyKeyMessage(\n inputs: AddOrderlyKeyInputs & { chainId: number },\n) {\n const {\n publicKey,\n brokerId,\n expiration = 365,\n timestamp = Date.now(),\n scope,\n tag,\n chainId,\n subAccountId,\n } = inputs;\n const message = {\n brokerId: brokerId,\n chainType: \"SOL\",\n orderlyKey: publicKey,\n scope: scope || \"read,trading,asset\",\n chainId,\n timestamp,\n expiration: timestamp + 1000 * 60 * 60 * 24 * expiration,\n ...(typeof tag !== \"undefined\" ? { tag } : {}),\n ...(typeof subAccountId !== \"undefined\" ? { subAccountId } : {}),\n };\n\n const brokerIdHash = solidityPackedKeccak256([\"string\"], [message.brokerId]);\n\n const orderlyKeyHash = solidityPackedKeccak256(\n [\"string\"],\n [message.orderlyKey],\n );\n const scopeHash = solidityPackedKeccak256([\"string\"], [message.scope]);\n const abicoder = AbiCoder.defaultAbiCoder();\n const msgToSign = keccak256(\n hexToBytes(\n abicoder.encode(\n [\"bytes32\", \"bytes32\", \"bytes32\", \"uint256\", \"uint256\", \"uint256\"],\n [\n brokerIdHash,\n orderlyKeyHash,\n scopeHash,\n message.chainId,\n message.timestamp,\n message.expiration,\n ],\n ),\n ),\n );\n const msgToSignHex = bytesToHex(msgToSign);\n const msgToSignTextEncoded: Uint8Array = new TextEncoder().encode(\n msgToSignHex,\n );\n return [message, msgToSignTextEncoded];\n}\n\nexport function registerAccountMessage(\n inputs: RegisterAccountInputs & {\n chainId: number;\n },\n) {\n const { chainId, registrationNonce, brokerId, timestamp } = inputs;\n\n const message = {\n brokerId,\n chainId,\n timestamp,\n registrationNonce,\n };\n const brokerIdHash = solidityPackedKeccak256([\"string\"], [message.brokerId]);\n const abicoder = AbiCoder.defaultAbiCoder();\n const msgToSign = keccak256(\n hexToBytes(\n abicoder.encode(\n [\"bytes32\", \"uint256\", \"uint256\", \"uint256\"],\n [\n brokerIdHash,\n message.chainId,\n message.timestamp,\n message.registrationNonce,\n ],\n ),\n ),\n );\n const msgToSignHex = bytesToHex(msgToSign);\n const msgToSignTextEncoded: Uint8Array = new TextEncoder().encode(\n msgToSignHex,\n );\n return [message, msgToSignTextEncoded];\n}\n\nexport function withdrawMessage(\n inputs: WithdrawInputs & {\n chainId: number;\n },\n) {\n const { chainId, receiver, token, amount, nonce, brokerId } = inputs;\n const timestamp = Date.now();\n\n const message = {\n brokerId,\n chainId,\n receiver,\n token: token,\n amount: amount,\n withdrawNonce: nonce,\n timestamp,\n chainType: \"SOL\",\n };\n\n const brokerIdHash = solidityPackedKeccak256([\"string\"], [message.brokerId]);\n const tokenSymbolHash = solidityPackedKeccak256([\"string\"], [message.token]);\n const salt = keccak256(Buffer.from(\"Orderly Network\"));\n const abicoder = AbiCoder.defaultAbiCoder();\n\n const msgToSign = keccak256(\n hexToBytes(\n abicoder.encode(\n [\n \"bytes32\",\n \"bytes32\",\n \"uint256\",\n \"bytes32\",\n \"uint256\",\n \"uint64\",\n \"uint64\",\n \"bytes32\",\n ],\n [\n brokerIdHash,\n tokenSymbolHash,\n chainId,\n bs58Decode(message.receiver),\n message.amount,\n message.withdrawNonce,\n timestamp,\n salt,\n ],\n ),\n ),\n );\n const msgToSignHex = bytesToHex(msgToSign);\n const msgToSignTextEncoded: Uint8Array = new TextEncoder().encode(\n msgToSignHex,\n );\n return [message, msgToSignTextEncoded];\n}\n\nexport function settleMessage(\n inputs: SettleInputs & {\n chainId: number;\n },\n) {\n const { settlePnlNonce, brokerId, chainId, timestamp } = inputs;\n\n const message = {\n brokerId: brokerId,\n chainId: chainId,\n timestamp: timestamp,\n chainType: \"SOL\",\n settleNonce: settlePnlNonce,\n };\n const brokerIdHash = solidityPackedKeccak256([\"string\"], [brokerId]);\n\n const abicoder = AbiCoder.defaultAbiCoder();\n const msgToSign = keccak256(\n hexToBytes(\n abicoder.encode(\n [\"bytes32\", \"uint256\", \"uint64\", \"uint64\"],\n [brokerIdHash, message.chainId, message.settleNonce, message.timestamp],\n ),\n ),\n );\n const msgToSignHex = bytesToHex(msgToSign);\n const msgToSignTextEncoded: Uint8Array = new TextEncoder().encode(\n msgToSignHex,\n );\n return [message, msgToSignTextEncoded];\n}\n\nexport enum MsgType {\n Deposit = 0,\n // Add other message types if needed\n}\n\nexport interface LzMessage {\n msgType: MsgType;\n payload: Buffer;\n}\n\nexport function encodeLzMessage(message: LzMessage): Buffer {\n const msgTypeBuffer = Buffer.alloc(1);\n msgTypeBuffer.writeUInt8(message.msgType);\n return Buffer.concat([msgTypeBuffer, message.payload]);\n}\n\nexport async function getDepositQuoteFee({\n vaultAddress,\n userAddress,\n connection,\n depositData,\n}: {\n vaultAddress: string;\n userAddress: string;\n connection: Connection;\n depositData: {\n tokenHash: string;\n brokerHash: string;\n accountId: string;\n USDCAddress: string;\n tokenAmount: string;\n };\n}) {\n console.log(\"-- vaultAddress\", vaultAddress);\n const appProgramId = new PublicKey(vaultAddress);\n const DST_EID = getDstEID(appProgramId);\n\n const program = new Program<SolanaVault>(VaultIDL, appProgramId, {\n connection,\n });\n const userPublicKey = new PublicKey(userAddress);\n\n const oappConfigPDA = getOAppConfigPda(appProgramId);\n const peerPDA = getPeerPda(appProgramId, oappConfigPDA, DST_EID);\n const endorcedPDA = getEndorcedOptionsPda(\n appProgramId,\n oappConfigPDA,\n DST_EID,\n );\n const sendLibConfigPDA = getSendLibConfigPda(oappConfigPDA, DST_EID);\n const defaultSendLibPDA = getDefaultSendLibConfigPda(DST_EID);\n\n const endpointSettingPDA = getEndpointSettingPda();\n const noncePDA = getNoncePda(appProgramId, oappConfigPDA, DST_EID);\n const sendConfigPDA = getSendConfigPda(oappConfigPDA, DST_EID);\n const defaultSendConfigPDA = getDefaultSendConfigPda(DST_EID);\n const executorConfigPDA = getExecutorConfigPda();\n const priceFeedPDA = getPriceFeedPda();\n const dvnConfigPDA = getDvnConfigPda();\n\n const messageLibPDA = getMessageLibPda(SEND_LIB_PROGRAM_ID);\n const messageLibInfoPDA = getMessageLibInfoPda(messageLibPDA);\n const vaultAuthorityPDA = getVaultAuthorityPda(appProgramId);\n\n const depositParams = getDepositParams(userAddress, depositData);\n\n // deposit fee\n const quoteFee = await program.methods\n .oappQuote(depositParams)\n .accounts({\n oappConfig: oappConfigPDA,\n peer: peerPDA,\n enforcedOptions: endorcedPDA,\n vaultAuthority: vaultAuthorityPDA,\n })\n .remainingAccounts([\n // ENDPOINT solana/programs/programs/uln/src/instructions/endpoint/send.rs\n {\n pubkey: ENDPOINT_PROGRAM_ID,\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: SEND_LIB_PROGRAM_ID,\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: sendLibConfigPDA, // send_library_config\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: defaultSendLibPDA, // default_send_library_config\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: messageLibInfoPDA, // send_library_info\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: endpointSettingPDA, // endpoint settings\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: noncePDA, // nonce\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: messageLibPDA,\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: sendConfigPDA,\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: defaultSendConfigPDA,\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: EXECUTOR_PROGRAM_ID,\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: executorConfigPDA,\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: PRICE_FEED_PROGRAM_ID,\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: priceFeedPDA,\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: DVN_PROGRAM_ID,\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: dvnConfigPDA,\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: PRICE_FEED_PROGRAM_ID,\n isWritable: false,\n isSigner: false,\n },\n {\n pubkey: priceFeedPDA,\n isWritable: false,\n isSigner: false,\n },\n ])\n .instruction();\n\n const lastBlockHash = await connection.getLatestBlockhash();\n\n const lookupTableAddress = getLookupTableAddress(appProgramId);\n const lookupTableAccount = await getLookupTableAccount(\n connection,\n lookupTableAddress,\n );\n if (!lookupTableAccount) {\n console.log(\"-- lookup table account error\");\n throw new Error(\"-- lookup table account error\");\n }\n const feeMsg = new TransactionMessage({\n payerKey: userPublicKey,\n recentBlockhash: lastBlockHash.blockhash,\n instructions: [quoteFee],\n }).compileToV0Message([lookupTableAccount]);\n\n const feeTx = new VersionedTransaction(feeMsg);\n\n const feeRes = await connection.simulateTransaction(feeTx);\n\n console.log(\"-- feeRes\", feeRes);\n if (feeRes.value.err) {\n const errorInfo =\n typeof feeRes.value.err === \"object\"\n ? JSON.stringify(feeRes.value.err)\n : feeRes.value.err;\n\n if (errorInfo.toString().includes(\"AccountNotFound\")) {\n throw new Error(\"Error: Account gas is insufficient.\");\n }\n\n throw new Error(`Error: ${errorInfo}`);\n }\n const returnPrefix = `Program return: ${program.programId} `;\n const returnLogEntry = feeRes.value.logs!.find((log) =>\n log.startsWith(returnPrefix),\n );\n if (!returnLogEntry) {\n throw new Error(\"Error: get deposit fee error\");\n }\n\n // Slice out the prefix to get the base64 return data\n const encodedReturnData = returnLogEntry.slice(returnPrefix.length);\n\n // Convert the Base64 return data\n const decodedBuffer = Buffer.from(encodedReturnData, \"base64\");\n console.log(\n decodedBuffer.readBigUInt64LE(0),\n decodedBuffer.readBigUInt64LE(1),\n );\n return decodedBuffer.readBigUInt64LE(0);\n}\nconst getDepositParams = (\n userAddress: string,\n depositData: {\n tokenHash: string;\n brokerHash: string;\n accountId: string;\n USDCAddress: string;\n tokenAmount: string;\n },\n) => {\n const brokerHash = depositData.brokerHash;\n const codedBrokerHash = Array.from(Buffer.from(brokerHash.slice(2), \"hex\"));\n\n const tokenHash = depositData.tokenHash;\n const codedTokenHash = Array.from(Buffer.from(tokenHash.slice(2), \"hex\"));\n\n const solAccountId = depositData.accountId;\n const codedAccountId = Array.from(Buffer.from(solAccountId.slice(2), \"hex\"));\n const userPublicKey = new PublicKey(userAddress);\n\n return {\n accountId: codedAccountId,\n brokerHash: codedBrokerHash,\n tokenHash: codedTokenHash,\n userAddress: Array.from(userPublicKey.toBuffer()),\n tokenAmount: new BN(depositData.tokenAmount),\n };\n};\n\nexport async function deposit({\n vaultAddress,\n userAddress,\n connection,\n sendTransaction,\n depositData,\n}: {\n vaultAddress: string;\n userAddress: string;\n connection: Connection;\n sendTransaction: WalletAdapterProps[\"sendTransaction\"];\n depositData: {\n tokenHash: string;\n brokerHash: string;\n accountId: string;\n USDCAddress: string;\n tokenAmount: string;\n };\n}) {\n const brokerHash = depositData.brokerHash;\n const tokenHash = depositData.tokenHash;\n\n console.log(\"-- vault address\", vaultAddress);\n const appProgramId = new PublicKey(vaultAddress);\n const program = new Program<SolanaVault>(VaultIDL, appProgramId, {\n connection,\n });\n const usdc = new PublicKey(depositData.USDCAddress);\n const userPublicKey = new PublicKey(userAddress);\n const userUSDCAccount = getUSDCAccounts(usdc, userPublicKey);\n const vaultAuthorityPda = getVaultAuthorityPda(appProgramId);\n const vaultUSDCAccount = getUSDCAccounts(usdc, vaultAuthorityPda);\n const allowedBrokerPDA = getBrokerPDA(appProgramId, brokerHash);\n const allowedTokenPDA = getTokenPDA(appProgramId, tokenHash);\n const oappConfigPDA = getOAppConfigPda(appProgramId);\n console.log(\"-- oappconfig pda\", oappConfigPDA.toBase58());\n const DST_EID = getDstEID(appProgramId);\n // const lzPDA = getLzReceiveTypesPda(appProgramId, oappConfigPDA);\n const peerPDA = getPeerPda(appProgramId, oappConfigPDA, DST_EID);\n const endorcedPDA = getEndorcedOptionsPda(\n appProgramId,\n oappConfigPDA,\n DST_EID,\n );\n const sendLibPDA = getSendLibPda();\n const sendLibConfigPDA = getSendLibConfigPda(oappConfigPDA, DST_EID);\n const defaultSendLibPDA = getDefaultSendLibConfigPda(DST_EID);\n const sendLibInfoPDA = getSendLibInfoPda(sendLibPDA);\n\n const endpointSettingPDA = getEndpointSettingPda();\n const noncePDA = getNoncePda(appProgramId, oappConfigPDA, DST_EID);\n const eventAuthorityPDA = getEventAuthorityPda();\n const ulnSettingPDA = getUlnSettingPda();\n const sendConfigPDA = getSendConfigPda(oappConfigPDA, DST_EID);\n const defaultSendConfigPDA = getDefaultSendConfigPda(DST_EID);\n const ulnEventAuthorityPDA = getUlnEventAuthorityPda();\n const executorConfigPDA = getExecutorConfigPda();\n const priceFeedPDA = getPriceFeedPda();\n const dvnConfigPDA = getDvnConfigPda();\n\n const vaultDepositParams = getDepositParams(userAddress, depositData);\n\n const fee = await getDepositQuoteFee({\n vaultAddress,\n userAddress,\n connection,\n depositData,\n });\n\n const sendParam = {\n nativeFee: new BN(fee.toString()),\n lzTokenFee: new BN(0),\n };\n\n // const sendParam = {\n // nativeFee: new BN(1_000_000_000),\n // lzTokenFee:new BN(0),\n //\n // }\n console.log(\"--- value params\", {\n vaultDepositParams,\n sendParam,\n });\n const ixDepositEntry = await program.methods\n .deposit(vaultDepositParams, sendParam)\n .accounts({\n userTokenAccount: userUSDCAccount,\n vaultAuthority: vaultAuthorityPda,\n vaultTokenAccount: vaultUSDCAccount,\n depositToken: usdc,\n user: userPublicKey,\n peer: peerPDA,\n enforcedOptions: endorcedPDA,\n oappConfig: oappConfigPDA,\n allowedBroker: allowedBrokerPDA,\n allowedToken: allowedTokenPDA,\n })\n .remainingAccounts([\n // ENDPOINT solana/programs/programs/uln/src/instructions/endpoint/send.rs\n {\n isSigner: false,\n isWritable: false,\n pubkey: ENDPOINT_PROGRAM_ID,\n },\n {\n isSigner: false,\n isWritable: false,\n // 0\n pubkey: oappConfigPDA,\n },\n {\n isSigner: false,\n isWritable: false,\n pubkey: SEND_LIB_PROGRAM_ID,\n },\n {\n isSigner: false,\n isWritable: false,\n // 7\n pubkey: sendLibConfigPDA,\n },\n {\n isSigner: false,\n isWritable: false,\n // 9\n pubkey: defaultSendLibPDA,\n },\n {\n isSigner: false,\n isWritable: false,\n // 8\n pubkey: sendLibInfoPDA,\n },\n {\n isSigner: false,\n isWritable: false,\n // 14\n pubkey: endpointSettingPDA,\n },\n {\n isSigner: false,\n isWritable: true,\n // 15\n pubkey: noncePDA,\n },\n {\n isSigner: false,\n isWritable: false,\n // 3\n pubkey: eventAuthorityPDA,\n },\n // ULN solana/programs/programs/uln/src/instructions/endpoint/send.rs\n {\n isSigner: false,\n isWritable: false,\n pubkey: ENDPOINT_PROGRAM_ID,\n },\n {\n isSigner: false,\n isWritable: false,\n // 13\n pubkey: ulnSettingPDA,\n },\n {\n isSigner: false,\n isWritable: false,\n // 10\n pubkey: sendConfigPDA,\n },\n {\n isSigner: false,\n isWritable: false,\n // 11\n pubkey: defaultSendConfigPDA,\n },\n {\n isSigner: true,\n isWritable: false,\n pubkey: userPublicKey,\n },\n {\n isSigner: false,\n isWritable: false,\n pubkey: TREASURY_PROGRAM_ID,\n },\n {\n isSigner: false,\n isWritable: false,\n pubkey: SystemProgram.programId,\n },\n {\n isSigner: false,\n isWritable: false,\n // 12\n pubkey: ulnEventAuthorityPDA,\n },\n {\n isSigner: false,\n isWritable: false,\n pubkey: SEND_LIB_PROGRAM_ID,\n },\n {\n isSigner: false,\n isWritable: false,\n pubkey: EXECUTOR_PROGRAM_ID,\n },\n {\n isSigner: false,\n isWritable: true,\n // 16\n pubkey: executorConfigPDA,\n },\n {\n isSigner: false,\n isWritable: false,\n pubkey: PRICE_FEED_PROGRAM_ID,\n },\n {\n isSigner: false,\n isWritable: false,\n // 17\n pubkey: priceFeedPDA,\n },\n {\n isSigner: false,\n isWritable: false,\n pubkey: DVN_PROGRAM_ID,\n },\n {\n isSigner: false,\n isWritable: true,\n // 18\n pubkey: dvnConfigPDA,\n },\n {\n isSigner: false,\n isWritable: false,\n pubkey: PRICE_FEED_PROGRAM_ID,\n },\n {\n isSigner: false,\n isWritable: false,\n // 17\n pubkey: priceFeedPDA,\n },\n ])\n .instruction();\n\n const lookupTableAddress = getLookupTableAddress(appProgramId);\n const lookupTableAccount = await getLookupTableAccount(\n connection,\n lookupTableAddress,\n );\n if (!lookupTableAccount) {\n console.log(\"-- lookup table account error\");\n return;\n }\n\n const ixAddComputeBudget = ComputeBudgetProgram.setComputeUnitLimit({\n units: 400_000,\n });\n\n const lastBlockHash = await connection.getLatestBlockhash();\n const msg = new TransactionMessage({\n payerKey: userPublicKey,\n recentBlockhash: lastBlockHash.blockhash,\n instructions: [ixDepositEntry, ixAddComputeBudget],\n }).compileToV0Message([lookupTableAccount]);\n\n const tx = new VersionedTransaction(msg);\n\n const res = await sendTransaction(tx, connection);\n console.log(\"res\", res);\n return res;\n}\n\nexport function checkIsLedgerWallet(userAddress: string): boolean {\n const info = window.localStorage.getItem(LedgerWalletKey);\n if (!info) {\n return false;\n }\n const addressArr = JSON.parse(info ?? \"[]\");\n console.log(\"-- addressArr\", addressArr);\n if (addressArr.includes(userAddress)) {\n return true;\n }\n return false;\n}\n","import { PublicKey } from \"@solana/web3.js\";\nimport { addressToBytes32 } from \"@layerzerolabs/lz-v2-utilities\";\n\n\nexport const ENDPOINT_PROGRAM_ID = new PublicKey(\"76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6\");\nexport const SEND_LIB_PROGRAM_ID = new PublicKey(\"7a4WjyR8VZ7yZz5XJAKm39BUGn5iT9CKcv2pmG9tdXVH\");\nexport const EXECUTOR_PROGRAM_ID = new PublicKey(\"6doghB248px58JSSwG4qejQ46kFMW4AMj7vzJnWZHNZn\");\nexport const PRICE_FEED_PROGRAM_ID = new PublicKey(\"8ahPGPjEbpgGaZx2NV1iG5Shj7TDwvsjkEDcGWjt94TP\");\nexport const RECEIVE_LIB_PROGRAM_ID = SEND_LIB_PROGRAM_ID;\nexport const TREASURY_PROGRAM_ID = SEND_LIB_PROGRAM_ID;\nexport const DVN_PROGRAM_ID = new PublicKey(\"HtEYV4xB4wvsj5fgTkcfuChYpvGYzgzwvNhgDZQNh7wW\");\nexport const VAULT_AUTHORITY_SEED = \"VaultAuthority\";\nexport const BROKER_SEED = \"Broker\";\nexport const TOKEN_SEED = \"Token\";\n// fro dev\n// export const PEER_ADDRESS = addressToBytes32('0x9Dc724b24146BeDD2dA28b8C4B74126169B8f312');\n// for qa\nexport const DEV_PEER_ADDRESS = addressToBytes32(\"0x9Dc724b24146BeDD2dA28b8C4B74126169B8f312\");\nexport const QA_PEER_ADDRESS = addressToBytes32(\"0x45b6C6266A7A2170617d8A27A50C642fd68b91c4\");\nexport const STAGING_PEER_ADDRESS = addressToBytes32(\"0x5Bf771A65d057e778C5f0Ed52A0003316f94322D\");\nexport const MAINNET_PEER_ADDRESS = addressToBytes32(\"0xCecAe061aa078e13b5e70D5F9eCee90a3F2B6AeA\");\n\nexport const DEV_DST_EID = 40200;\nexport const MAIN_DST_EID = 30213;\n\nexport const DEV_LOOKUP_TABLE_ADDRESS = new PublicKey(\"BWp8HaYYhiNHekt3zgQhqoCrRftneGxxfgKmCZ6svHN\");\nexport const QA_LOOKUP_TABLE_ADDRESS = new PublicKey(\"BswrQQoPKAFojTuJutZcBMtigAgTghEH4M8ofn3EG2X2\");\nexport const STAGING_LOOKUP_TABLE_ADDRESS = new PublicKey(\"BbGKfxuPwDmu58BjPpd7PMG69TqnZjSpKaLDMgf9E9Dr\");\nexport const MAINNET_LOOKUP_TABLE_ADDRESS = new PublicKey(\"8iq7xCQt3bLdRRn4A46d5GuaXYinBoiAhbe2sUmZVzwg\");\n\n\nexport const DEV_OAPP_PROGRAM_ID = new PublicKey(\"EYJq9eU4GMRUriUJBgGoZ8YLQBXcWaciXuSsEXE7ieQS\");\nexport const QA_OAPP_PROGRAM_ID = new PublicKey(\"5zBjLor7vEraAt4zp2H82sy9MSqFoDnNa1Lx6EYKTYRZ\");\nexport const STAGING_OAPP_PROGRAM_ID = new PublicKey(\"9shwxWDUNhtwkHocsUAmrNAQfBH2DHh4njdAEdHZZkF2\");\nexport const MAINNET_OAPP_PROGRAM_ID = new PublicKey(\"ErBmAD61mGFKvrFNaTJuxoPwqrS8GgtwtqJTJVjFWx9Q\");\n","export type SolanaVault = {\n \"version\": \"0.1.0\",\n \"name\": \"solana_vault\",\n \"instructions\": [\n {\n \"name\": \"initVault\",\n \"accounts\": [\n {\n \"name\": \"signer\",\n \"isMut\": true,\n \"isSigner\": true\n },\n {\n \"name\": \"vaultAuthority\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"systemProgram\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"InitVaultParams\"\n }\n }\n ]\n },\n {\n \"name\": \"deposit\",\n \"accounts\": [\n {\n \"name\": \"user\",\n \"isMut\": true,\n \"isSigner\": true\n },\n {\n \"name\": \"userTokenAccount\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"vaultAuthority\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"vaultTokenAccount\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"depositToken\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"peer\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"enforcedOptions\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"oappConfig\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"allowedBroker\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"allowedToken\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"tokenProgram\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"associatedTokenProgram\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"systemProgram\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"depositParams\",\n \"type\": {\n \"defined\": \"DepositParams\"\n }\n },\n {\n \"name\": \"oappParams\",\n \"type\": {\n \"defined\": \"OAppSendParams\"\n }\n }\n ],\n \"returns\": {\n \"defined\": \"MessagingReceipt\"\n }\n },\n {\n \"name\": \"initOapp\",\n \"accounts\": [\n {\n \"name\": \"payer\",\n \"isMut\": true,\n \"isSigner\": true\n },\n {\n \"name\": \"oappConfig\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"lzReceiveTypes\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"systemProgram\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"InitOAppParams\"\n }\n }\n ]\n },\n {\n \"name\": \"resetOapp\",\n \"accounts\": [\n {\n \"name\": \"admin\",\n \"isMut\": true,\n \"isSigner\": true\n },\n {\n \"name\": \"oappConfig\",\n \"isMut\": true,\n \"isSigner\": false\n }\n ],\n \"args\": []\n },\n {\n \"name\": \"reinitOapp\",\n \"accounts\": [\n {\n \"name\": \"owner\",\n \"isMut\": true,\n \"isSigner\": true\n },\n {\n \"name\": \"oappConfig\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"vaultAuthority\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"systemProgram\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"ReinitOAppParams\"\n }\n }\n ]\n },\n {\n \"name\": \"resetVault\",\n \"accounts\": [\n {\n \"name\": \"owner\",\n \"isMut\": true,\n \"isSigner\": true\n },\n {\n \"name\": \"vaultAuthority\",\n \"isMut\": true,\n \"isSigner\": false\n }\n ],\n \"args\": []\n },\n {\n \"name\": \"reinitVault\",\n \"accounts\": [\n {\n \"name\": \"admin\",\n \"isMut\": true,\n \"isSigner\": true\n },\n {\n \"name\": \"vaultAuthority\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"oappConfig\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"systemProgram\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"ReinitVaultParams\"\n }\n }\n ]\n },\n {\n \"name\": \"setBroker\",\n \"accounts\": [\n {\n \"name\": \"admin\",\n \"isMut\": true,\n \"isSigner\": true\n },\n {\n \"name\": \"allowedBroker\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"oappConfig\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"systemProgram\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"SetBrokerParams\"\n }\n }\n ]\n },\n {\n \"name\": \"setToken\",\n \"accounts\": [\n {\n \"name\": \"admin\",\n \"isMut\": true,\n \"isSigner\": true\n },\n {\n \"name\": \"allowedToken\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"oappConfig\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"mintAccount\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"systemProgram\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"SetTokenParams\"\n }\n }\n ]\n },\n {\n \"name\": \"setOrderDelivery\",\n \"accounts\": [\n {\n \"name\": \"owner\",\n \"isMut\": true,\n \"isSigner\": true\n },\n {\n \"name\": \"vaultAuthority\",\n \"isMut\": true,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"SetOrderDeliveryParams\"\n }\n }\n ]\n },\n {\n \"name\": \"oappQuote\",\n \"accounts\": [\n {\n \"name\": \"oappConfig\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"peer\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"enforcedOptions\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"vaultAuthority\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"DepositParams\"\n }\n }\n ],\n \"returns\": {\n \"defined\": \"MessagingFee\"\n }\n },\n {\n \"name\": \"lzReceive\",\n \"accounts\": [\n {\n \"name\": \"payer\",\n \"isMut\": true,\n \"isSigner\": true\n },\n {\n \"name\": \"peer\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"oappConfig\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"user\",\n \"isMut\": false,\n \"isSigner\": false,\n \"docs\": [\n \"CHECK\"\n ]\n },\n {\n \"name\": \"userDepositWallet\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"vaultAuthority\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"vaultDepositWallet\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"depositToken\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"tokenProgram\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"systemProgram\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"eventAuthority\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"program\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"OAppLzReceiveParams\"\n }\n }\n ]\n },\n {\n \"name\": \"lzReceiveTypes\",\n \"accounts\": [\n {\n \"name\": \"oappConfig\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"OAppLzReceiveParams\"\n }\n }\n ],\n \"returns\": {\n \"vec\": {\n \"defined\": \"oapp::endpoint_cpi::LzAccount\"\n }\n }\n },\n {\n \"name\": \"setRateLimit\",\n \"accounts\": [\n {\n \"name\": \"admin\",\n \"isMut\": false,\n \"isSigner\": true\n },\n {\n \"name\": \"peer\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"oappConfig\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"SetRateLimitParams\"\n }\n }\n ]\n },\n {\n \"name\": \"setDelegate\",\n \"accounts\": [\n {\n \"name\": \"admin\",\n \"isMut\": false,\n \"isSigner\": true\n },\n {\n \"name\": \"oappConfig\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"SetDelegateParams\"\n }\n }\n ]\n },\n {\n \"name\": \"transferAdmin\",\n \"accounts\": [\n {\n \"name\": \"admin\",\n \"isMut\": false,\n \"isSigner\": true\n },\n {\n \"name\": \"oappConfig\",\n \"isMut\": true,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"TransferAdminParams\"\n }\n }\n ]\n },\n {\n \"name\": \"setPeer\",\n \"accounts\": [\n {\n \"name\": \"admin\",\n \"isMut\": true,\n \"isSigner\": true\n },\n {\n \"name\": \"peer\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"oappConfig\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"systemProgram\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"SetPeerParams\"\n }\n }\n ]\n },\n {\n \"name\": \"setEnforcedOptions\",\n \"accounts\": [\n {\n \"name\": \"admin\",\n \"isMut\": true,\n \"isSigner\": true\n },\n {\n \"name\": \"enforcedOptions\",\n \"isMut\": true,\n \"isSigner\": false\n },\n {\n \"name\": \"oappConfig\",\n \"isMut\": false,\n \"isSigner\": false\n },\n {\n \"name\": \"systemProgram\",\n \"isMut\": false,\n \"isSigner\": false\n }\n ],\n \"args\": [\n {\n \"name\": \"params\",\n \"type\": {\n \"defined\": \"SetEnforcedOptionsParams\"\n }\n }\n ]\n }\n ],\n \"accounts\": [\n {\n \"name\": \"enforcedOptions\",\n \"type\": {\n \"kind\": \"struct\",\n \"fields\": [\n {\n \"name\": \"send\",\n \"type\": \"bytes\"\n },\n {\n \"name\": \"sendAndCall\",\n \"type\": \"bytes\"\n },\n {\n \"name\": \"bump\",\n \"type\": \"u8\"\n }\n ]\n }\n },\n {\n \"name\": \"oAppConfig\",\n \"type\": {\n \"kind\": \"struct\",\n \"fields\": [\n {\n \"name\": \"endpointProgram\",\n \"type\": \"publicKey\"\n },\n {\n \"name\": \"bump\",\n \"type\": \"u8\"\n },\n {\n \"name\": \"admin\",\n \"type\": \"publicKey\"\n },\n {\n \"name\": \"usdcHash\",\n \"type\": {\n \"array\": [\n \"u8\",\n 32\n ]\n }\n },\n {\n \"name\": \"usdcMint\",\n \"type\": \"publicKey\"\n }\n ]\n }\n },\n {\n \"name\": \"oAppLzReceiveTypesAccounts\",\n \"type\": {\n \"kind\": \"struct\",\n \"fields\": [\n {\n \"name\": \"oappConfig\",\n \"type\": \"publicKey\"\n }\n ]\n }\n },\n {\n \"name\": \"peer\",\n \"type\": {\n \"kind\": \"struct\",\n \"fields\": [\n {\n \"name\": \"address\",\n \"type\": {\n \"array\": [\n \"u8\",\n 32\n ]\n }\n },\n {\n \"name\": \"rateLimiter\",\n