@lifi/sdk-provider-solana 4.0.0-beta.5 → 4.0.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/actions/getSolanaBalance.js +25 -5
- package/dist/cjs/actions/getSolanaBalance.js.map +1 -1
- package/dist/cjs/core/tasks/SolanaSignAndExecuteTask.js +1 -2
- package/dist/cjs/core/tasks/SolanaSignAndExecuteTask.js.map +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/version.js.map +1 -1
- package/dist/esm/actions/getSolanaBalance.js +25 -5
- package/dist/esm/actions/getSolanaBalance.js.map +1 -1
- package/dist/esm/core/tasks/SolanaSignAndExecuteTask.js +1 -2
- package/dist/esm/core/tasks/SolanaSignAndExecuteTask.js.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/package.json +3 -3
- package/src/actions/getSolanaBalance.ts +23 -17
- package/src/core/tasks/SolanaSignAndExecuteTask.ts +1 -1
- package/src/version.ts +1 -1
- package/dist/cjs/utils/withTimeout.d.ts +0 -26
- package/dist/cjs/utils/withTimeout.js +0 -35
- package/dist/cjs/utils/withTimeout.js.map +0 -1
- package/dist/esm/utils/withTimeout.d.ts +0 -26
- package/dist/esm/utils/withTimeout.d.ts.map +0 -1
- package/dist/esm/utils/withTimeout.js +0 -34
- package/dist/esm/utils/withTimeout.js.map +0 -1
- package/src/utils/withTimeout.ts +0 -50
|
@@ -29,18 +29,38 @@ const getSolanaBalanceDefault = async (client, _chainId, tokens, walletAddress)
|
|
|
29
29
|
}).send()), { id: `${getSolanaBalanceDefault.name}.getTokenAccountsByOwner.${Token2022ProgramId}` })
|
|
30
30
|
]);
|
|
31
31
|
const blockNumber = slot.status === "fulfilled" ? BigInt(slot.value) : 0n;
|
|
32
|
-
const
|
|
33
|
-
const
|
|
32
|
+
const nativeBalanceOk = balance.status === "fulfilled";
|
|
33
|
+
const solBalance = nativeBalanceOk ? BigInt(balance.value.value) : 0n;
|
|
34
|
+
const tokenProgramOk = tokenAccountsByOwner.status === "fulfilled";
|
|
35
|
+
const token2022ProgramOk = token2022AccountsByOwner.status === "fulfilled";
|
|
36
|
+
const walletTokenAmounts = [...tokenProgramOk ? tokenAccountsByOwner.value.value : [], ...token2022ProgramOk ? token2022AccountsByOwner.value.value : []].reduce((tokenAmounts, value) => {
|
|
34
37
|
const tokenAccount = value.account.data.parsed.info;
|
|
35
38
|
const amount = BigInt(tokenAccount.tokenAmount.amount);
|
|
36
39
|
if (amount > 0n) tokenAmounts[tokenAccount.mint] = amount;
|
|
37
40
|
return tokenAmounts;
|
|
38
41
|
}, {});
|
|
39
|
-
|
|
42
|
+
const splZeroIsKnown = tokenProgramOk && token2022ProgramOk;
|
|
40
43
|
return tokens.map((token) => {
|
|
41
|
-
if (
|
|
44
|
+
if (token.address === SolSystemProgram) {
|
|
45
|
+
if (!nativeBalanceOk) return {
|
|
46
|
+
...token,
|
|
47
|
+
blockNumber
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
...token,
|
|
51
|
+
amount: solBalance,
|
|
52
|
+
blockNumber
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const found = walletTokenAmounts[token.address];
|
|
56
|
+
if (found !== void 0) return {
|
|
42
57
|
...token,
|
|
43
|
-
amount:
|
|
58
|
+
amount: found,
|
|
59
|
+
blockNumber
|
|
60
|
+
};
|
|
61
|
+
if (splZeroIsKnown) return {
|
|
62
|
+
...token,
|
|
63
|
+
amount: 0n,
|
|
44
64
|
blockNumber
|
|
45
65
|
};
|
|
46
66
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getSolanaBalance.js","names":["callSolanaRpcsWithRetry"],"sources":["../../../src/actions/getSolanaBalance.ts"],"sourcesContent":["import type { SDKClient } from '@lifi/sdk'\nimport {\n type ChainId,\n type Token,\n type TokenAmount,\n withDedupe,\n} from '@lifi/sdk'\nimport { address, type JsonParsedTokenAccount } from '@solana/kit'\n\nimport { callSolanaRpcsWithRetry } from '../rpc/utils.js'\n\nconst SolSystemProgram = '11111111111111111111111111111111'\nconst TokenProgramId = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'\nconst Token2022ProgramId = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'\n\nexport const getSolanaBalance = async (\n client: SDKClient,\n walletAddress: string,\n tokens: Token[]\n): Promise<TokenAmount[]> => {\n if (tokens.length === 0) {\n return []\n }\n const { chainId } = tokens[0]\n for (const token of tokens) {\n if (token.chainId !== chainId) {\n console.warn('Requested tokens have to be on the same chain.')\n }\n }\n\n return getSolanaBalanceDefault(client, chainId, tokens, walletAddress)\n}\n\nconst getSolanaBalanceDefault = async (\n client: SDKClient,\n _chainId: ChainId,\n tokens: Token[],\n walletAddress: string\n): Promise<TokenAmount[]> => {\n // Convert addresses to Solana Kit's address type\n const accountAddress = address(walletAddress)\n const tokenProgramAddress = address(TokenProgramId)\n const token2022ProgramAddress = address(Token2022ProgramId)\n\n // Use Solana Kit's RPC API with the retry wrapper\n const [slot, balance, tokenAccountsByOwner, token2022AccountsByOwner] =\n await Promise.allSettled([\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc.getSlot({ commitment: 'confirmed' }).send()\n ),\n { id: `${getSolanaBalanceDefault.name}.getSlot` }\n ),\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc.getBalance(accountAddress, { commitment: 'confirmed' }).send()\n ),\n { id: `${getSolanaBalanceDefault.name}.getBalance` }\n ),\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc\n .getTokenAccountsByOwner(\n accountAddress,\n {\n programId: tokenProgramAddress,\n },\n {\n commitment: 'confirmed',\n encoding: 'jsonParsed',\n }\n )\n .send()\n ),\n {\n id: `${getSolanaBalanceDefault.name}.getTokenAccountsByOwner.${TokenProgramId}`,\n }\n ),\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc\n .getTokenAccountsByOwner(\n accountAddress,\n {\n programId: token2022ProgramAddress,\n },\n {\n commitment: 'confirmed',\n encoding: 'jsonParsed',\n }\n )\n .send()\n ),\n {\n id: `${getSolanaBalanceDefault.name}.getTokenAccountsByOwner.${Token2022ProgramId}`,\n }\n ),\n ])\n const blockNumber = slot.status === 'fulfilled' ? BigInt(slot.value) : 0n\n const
|
|
1
|
+
{"version":3,"file":"getSolanaBalance.js","names":["callSolanaRpcsWithRetry"],"sources":["../../../src/actions/getSolanaBalance.ts"],"sourcesContent":["import type { SDKClient } from '@lifi/sdk'\nimport {\n type ChainId,\n type Token,\n type TokenAmount,\n withDedupe,\n} from '@lifi/sdk'\nimport { address, type JsonParsedTokenAccount } from '@solana/kit'\n\nimport { callSolanaRpcsWithRetry } from '../rpc/utils.js'\n\nconst SolSystemProgram = '11111111111111111111111111111111'\nconst TokenProgramId = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'\nconst Token2022ProgramId = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'\n\nexport const getSolanaBalance = async (\n client: SDKClient,\n walletAddress: string,\n tokens: Token[]\n): Promise<TokenAmount[]> => {\n if (tokens.length === 0) {\n return []\n }\n const { chainId } = tokens[0]\n for (const token of tokens) {\n if (token.chainId !== chainId) {\n console.warn('Requested tokens have to be on the same chain.')\n }\n }\n\n return getSolanaBalanceDefault(client, chainId, tokens, walletAddress)\n}\n\nconst getSolanaBalanceDefault = async (\n client: SDKClient,\n _chainId: ChainId,\n tokens: Token[],\n walletAddress: string\n): Promise<TokenAmount[]> => {\n // Convert addresses to Solana Kit's address type\n const accountAddress = address(walletAddress)\n const tokenProgramAddress = address(TokenProgramId)\n const token2022ProgramAddress = address(Token2022ProgramId)\n\n // Use Solana Kit's RPC API with the retry wrapper\n const [slot, balance, tokenAccountsByOwner, token2022AccountsByOwner] =\n await Promise.allSettled([\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc.getSlot({ commitment: 'confirmed' }).send()\n ),\n { id: `${getSolanaBalanceDefault.name}.getSlot` }\n ),\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc.getBalance(accountAddress, { commitment: 'confirmed' }).send()\n ),\n { id: `${getSolanaBalanceDefault.name}.getBalance` }\n ),\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc\n .getTokenAccountsByOwner(\n accountAddress,\n {\n programId: tokenProgramAddress,\n },\n {\n commitment: 'confirmed',\n encoding: 'jsonParsed',\n }\n )\n .send()\n ),\n {\n id: `${getSolanaBalanceDefault.name}.getTokenAccountsByOwner.${TokenProgramId}`,\n }\n ),\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc\n .getTokenAccountsByOwner(\n accountAddress,\n {\n programId: token2022ProgramAddress,\n },\n {\n commitment: 'confirmed',\n encoding: 'jsonParsed',\n }\n )\n .send()\n ),\n {\n id: `${getSolanaBalanceDefault.name}.getTokenAccountsByOwner.${Token2022ProgramId}`,\n }\n ),\n ])\n const blockNumber = slot.status === 'fulfilled' ? BigInt(slot.value) : 0n\n const nativeBalanceOk = balance.status === 'fulfilled'\n const solBalance = nativeBalanceOk ? BigInt(balance.value.value) : 0n\n const tokenProgramOk = tokenAccountsByOwner.status === 'fulfilled'\n const token2022ProgramOk = token2022AccountsByOwner.status === 'fulfilled'\n\n const walletTokenAmounts = [\n ...(tokenProgramOk ? tokenAccountsByOwner.value.value : []),\n ...(token2022ProgramOk ? token2022AccountsByOwner.value.value : []),\n ].reduce(\n (tokenAmounts: Record<string, bigint>, value) => {\n const tokenAccount: JsonParsedTokenAccount =\n value.account.data.parsed.info\n const amount = BigInt(tokenAccount.tokenAmount.amount)\n if (amount > 0n) {\n tokenAmounts[tokenAccount.mint] = amount\n }\n return tokenAmounts\n },\n {} as Record<string, bigint>\n )\n\n // We can only confidently report 0n for an SPL mint when both Token and\n // Token2022 program queries succeeded — otherwise the mint may live in the\n // program whose query failed (e.g. PYUSD on Token2022).\n const splZeroIsKnown = tokenProgramOk && token2022ProgramOk\n\n const tokenAmounts: TokenAmount[] = tokens.map((token) => {\n const isNative = token.address === SolSystemProgram\n if (isNative) {\n if (!nativeBalanceOk) {\n return { ...token, blockNumber }\n }\n return { ...token, amount: solBalance, blockNumber }\n }\n const found = walletTokenAmounts[token.address]\n if (found !== undefined) {\n return { ...token, amount: found, blockNumber }\n }\n if (splZeroIsKnown) {\n return { ...token, amount: 0n, blockNumber }\n }\n return { ...token, blockNumber }\n })\n return tokenAmounts\n}\n"],"mappings":";;;;;AAWA,MAAM,mBAAmB;AACzB,MAAM,iBAAiB;AACvB,MAAM,qBAAqB;AAE3B,MAAa,mBAAmB,OAC9B,QACA,eACA,WAC2B;AAC3B,KAAI,OAAO,WAAW,EACpB,QAAO,EAAE;CAEX,MAAM,EAAE,YAAY,OAAO;AAC3B,MAAK,MAAM,SAAS,OAClB,KAAI,MAAM,YAAY,QACpB,SAAQ,KAAK,iDAAiD;AAIlE,QAAO,wBAAwB,QAAQ,SAAS,QAAQ,cAAc;;AAGxE,MAAM,0BAA0B,OAC9B,QACA,UACA,QACA,kBAC2B;CAE3B,MAAM,kBAAA,GAAA,YAAA,SAAyB,cAAc;CAC7C,MAAM,uBAAA,GAAA,YAAA,SAA8B,eAAe;CACnD,MAAM,2BAAA,GAAA,YAAA,SAAkC,mBAAmB;CAG3D,MAAM,CAAC,MAAM,SAAS,sBAAsB,4BAC1C,MAAM,QAAQ,WAAW;kCAGnBA,kBAAAA,wBAAwB,SAAS,QAC/B,IAAI,QAAQ,EAAE,YAAY,aAAa,CAAC,CAAC,MAAM,CAChD,EACH,EAAE,IAAI,GAAG,wBAAwB,KAAK,WAAW,CAClD;kCAGGA,kBAAAA,wBAAwB,SAAS,QAC/B,IAAI,WAAW,gBAAgB,EAAE,YAAY,aAAa,CAAC,CAAC,MAAM,CACnE,EACH,EAAE,IAAI,GAAG,wBAAwB,KAAK,cAAc,CACrD;kCAGGA,kBAAAA,wBAAwB,SAAS,QAC/B,IACG,wBACC,gBACA,EACE,WAAW,qBACZ,EACD;GACE,YAAY;GACZ,UAAU;GACX,CACF,CACA,MAAM,CACV,EACH,EACE,IAAI,GAAG,wBAAwB,KAAK,2BAA2B,kBAChE,CACF;kCAGGA,kBAAAA,wBAAwB,SAAS,QAC/B,IACG,wBACC,gBACA,EACE,WAAW,yBACZ,EACD;GACE,YAAY;GACZ,UAAU;GACX,CACF,CACA,MAAM,CACV,EACH,EACE,IAAI,GAAG,wBAAwB,KAAK,2BAA2B,sBAChE,CACF;EACF,CAAC;CACJ,MAAM,cAAc,KAAK,WAAW,cAAc,OAAO,KAAK,MAAM,GAAG;CACvE,MAAM,kBAAkB,QAAQ,WAAW;CAC3C,MAAM,aAAa,kBAAkB,OAAO,QAAQ,MAAM,MAAM,GAAG;CACnE,MAAM,iBAAiB,qBAAqB,WAAW;CACvD,MAAM,qBAAqB,yBAAyB,WAAW;CAE/D,MAAM,qBAAqB,CACzB,GAAI,iBAAiB,qBAAqB,MAAM,QAAQ,EAAE,EAC1D,GAAI,qBAAqB,yBAAyB,MAAM,QAAQ,EAAE,CACnE,CAAC,QACC,cAAsC,UAAU;EAC/C,MAAM,eACJ,MAAM,QAAQ,KAAK,OAAO;EAC5B,MAAM,SAAS,OAAO,aAAa,YAAY,OAAO;AACtD,MAAI,SAAS,GACX,cAAa,aAAa,QAAQ;AAEpC,SAAO;IAET,EAAE,CACH;CAKD,MAAM,iBAAiB,kBAAkB;AAmBzC,QAjBoC,OAAO,KAAK,UAAU;AAExD,MADiB,MAAM,YAAY,kBACrB;AACZ,OAAI,CAAC,gBACH,QAAO;IAAE,GAAG;IAAO;IAAa;AAElC,UAAO;IAAE,GAAG;IAAO,QAAQ;IAAY;IAAa;;EAEtD,MAAM,QAAQ,mBAAmB,MAAM;AACvC,MAAI,UAAU,KAAA,EACZ,QAAO;GAAE,GAAG;GAAO,QAAQ;GAAO;GAAa;AAEjD,MAAI,eACF,QAAO;GAAE,GAAG;GAAO,QAAQ;GAAI;GAAa;AAE9C,SAAO;GAAE,GAAG;GAAO;GAAa;GAChC"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_utils_base64ToUint8Array = require("../../utils/base64ToUint8Array.js");
|
|
3
3
|
const require_utils_getWalletFeature = require("../../utils/getWalletFeature.js");
|
|
4
|
-
const require_utils_withTimeout = require("../../utils/withTimeout.js");
|
|
5
4
|
let _lifi_sdk = require("@lifi/sdk");
|
|
6
5
|
let _solana_kit = require("@solana/kit");
|
|
7
6
|
let _solana_wallet_standard_features = require("@solana/wallet-standard-features");
|
|
@@ -13,7 +12,7 @@ var SolanaSignAndExecuteTask = class extends _lifi_sdk.BaseStepExecutionTask {
|
|
|
13
12
|
if (!action) throw new _lifi_sdk.TransactionError(_lifi_sdk.LiFiErrorCode.TransactionUnprepared, "Unable to prepare transaction. Action not found.");
|
|
14
13
|
const transactionRequestData = await (0, _lifi_sdk.getTransactionRequestData)(step, executionOptions);
|
|
15
14
|
const transactionBytesArray = (Array.isArray(transactionRequestData) ? transactionRequestData : [transactionRequestData]).map((data) => require_utils_base64ToUint8Array.base64ToUint8Array(data));
|
|
16
|
-
const signedTransactionOutputs = await
|
|
15
|
+
const signedTransactionOutputs = await (0, _lifi_sdk.withTimeout)(async () => {
|
|
17
16
|
const { signTransaction } = require_utils_getWalletFeature.getWalletFeature(wallet, _solana_wallet_standard_features.SolanaSignTransaction);
|
|
18
17
|
return signTransaction(...transactionBytesArray.map((transaction) => ({
|
|
19
18
|
account: walletAccount,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SolanaSignAndExecuteTask.js","names":["BaseStepExecutionTask","TransactionError","LiFiErrorCode","base64ToUint8Array","
|
|
1
|
+
{"version":3,"file":"SolanaSignAndExecuteTask.js","names":["BaseStepExecutionTask","TransactionError","LiFiErrorCode","base64ToUint8Array","getWalletFeature","SolanaSignTransaction"],"sources":["../../../../src/core/tasks/SolanaSignAndExecuteTask.ts"],"sourcesContent":["import {\n BaseStepExecutionTask,\n getTransactionRequestData,\n LiFiErrorCode,\n type TaskResult,\n TransactionError,\n withTimeout,\n} from '@lifi/sdk'\nimport { getTransactionCodec } from '@solana/kit'\nimport { SolanaSignTransaction } from '@solana/wallet-standard-features'\nimport type { SolanaStepExecutorContext } from '../../types.js'\nimport { base64ToUint8Array } from '../../utils/base64ToUint8Array.js'\nimport { getWalletFeature } from '../../utils/getWalletFeature.js'\n\nexport class SolanaSignAndExecuteTask extends BaseStepExecutionTask {\n async run(context: SolanaStepExecutorContext): Promise<TaskResult> {\n const {\n step,\n wallet,\n walletAccount,\n statusManager,\n executionOptions,\n isBridgeExecution,\n } = context\n\n const action = statusManager.findAction(\n step,\n isBridgeExecution ? 'CROSS_CHAIN' : 'SWAP'\n )\n if (!action) {\n throw new TransactionError(\n LiFiErrorCode.TransactionUnprepared,\n 'Unable to prepare transaction. Action not found.'\n )\n }\n\n const transactionRequestData = await getTransactionRequestData(\n step,\n executionOptions\n )\n\n // Handle both single transaction (string) and multiple transactions (array)\n const transactionDataArray = Array.isArray(transactionRequestData)\n ? transactionRequestData\n : [transactionRequestData]\n\n const transactionBytesArray = transactionDataArray.map((data) =>\n base64ToUint8Array(data)\n )\n\n const signedTransactionOutputs = await withTimeout(\n async () => {\n const { signTransaction } = getWalletFeature(\n wallet,\n SolanaSignTransaction\n )\n // Spread the inputs to sign all transactions at once\n return signTransaction(\n ...transactionBytesArray.map((transaction) => ({\n account: walletAccount,\n transaction,\n }))\n )\n },\n {\n // https://solana.com/docs/advanced/confirmation#transaction-expiration\n // Use 2 minutes to account for fluctuations\n timeout: 120_000,\n errorInstance: new TransactionError(\n LiFiErrorCode.TransactionExpired,\n 'Transaction has expired: blockhash is no longer recent enough.'\n ),\n }\n )\n\n if (signedTransactionOutputs.length === 0) {\n throw new TransactionError(\n LiFiErrorCode.TransactionUnprepared,\n 'No signed transaction returned from signer.'\n )\n }\n\n statusManager.updateAction(step, action.type, 'PENDING', {\n signedAt: Date.now(),\n })\n\n const transactionCodec = getTransactionCodec()\n\n // Decode all signed transactions\n const signedTransactions = signedTransactionOutputs.map((output) =>\n transactionCodec.decode(output.signedTransaction)\n )\n\n return {\n status: 'COMPLETED',\n context: { signedTransactions },\n }\n }\n}\n"],"mappings":";;;;;;;AAcA,IAAa,2BAAb,cAA8CA,UAAAA,sBAAsB;CAClE,MAAM,IAAI,SAAyD;EACjE,MAAM,EACJ,MACA,QACA,eACA,eACA,kBACA,sBACE;EAEJ,MAAM,SAAS,cAAc,WAC3B,MACA,oBAAoB,gBAAgB,OACrC;AACD,MAAI,CAAC,OACH,OAAM,IAAIC,UAAAA,iBACRC,UAAAA,cAAc,uBACd,mDACD;EAGH,MAAM,yBAAyB,OAAA,GAAA,UAAA,2BAC7B,MACA,iBACD;EAOD,MAAM,yBAJuB,MAAM,QAAQ,uBAAuB,GAC9D,yBACA,CAAC,uBAAuB,EAEuB,KAAK,SACtDC,iCAAAA,mBAAmB,KAAK,CACzB;EAED,MAAM,2BAA2B,OAAA,GAAA,UAAA,aAC/B,YAAY;GACV,MAAM,EAAE,oBAAoBC,+BAAAA,iBAC1B,QACAC,iCAAAA,sBACD;AAED,UAAO,gBACL,GAAG,sBAAsB,KAAK,iBAAiB;IAC7C,SAAS;IACT;IACD,EAAE,CACJ;KAEH;GAGE,SAAS;GACT,eAAe,IAAIJ,UAAAA,iBACjBC,UAAAA,cAAc,oBACd,iEACD;GACF,CACF;AAED,MAAI,yBAAyB,WAAW,EACtC,OAAM,IAAID,UAAAA,iBACRC,UAAAA,cAAc,uBACd,8CACD;AAGH,gBAAc,aAAa,MAAM,OAAO,MAAM,WAAW,EACvD,UAAU,KAAK,KAAK,EACrB,CAAC;EAEF,MAAM,oBAAA,GAAA,YAAA,sBAAwC;AAO9C,SAAO;GACL,QAAQ;GACR,SAAS,EAAE,oBANc,yBAAyB,KAAK,WACvD,iBAAiB,OAAO,OAAO,kBAAkB,CAClD,EAIgC;GAChC"}
|
package/dist/cjs/version.d.ts
CHANGED
package/dist/cjs/version.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
//#region src/version.ts
|
|
3
3
|
const name = "@lifi/sdk-provider-solana";
|
|
4
|
-
const version = "4.0.0-beta.
|
|
4
|
+
const version = "4.0.0-beta.6";
|
|
5
5
|
//#endregion
|
|
6
6
|
exports.name = name;
|
|
7
7
|
exports.version = version;
|
package/dist/cjs/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","names":[],"sources":["../../src/version.ts"],"sourcesContent":["export const name = '@lifi/sdk-provider-solana'\nexport const version = '4.0.0-beta.
|
|
1
|
+
{"version":3,"file":"version.js","names":[],"sources":["../../src/version.ts"],"sourcesContent":["export const name = '@lifi/sdk-provider-solana'\nexport const version = '4.0.0-beta.6'\n"],"mappings":";;AAAA,MAAa,OAAO;AACpB,MAAa,UAAU"}
|
|
@@ -28,18 +28,38 @@ const getSolanaBalanceDefault = async (client, _chainId, tokens, walletAddress)
|
|
|
28
28
|
}).send()), { id: `${getSolanaBalanceDefault.name}.getTokenAccountsByOwner.${Token2022ProgramId}` })
|
|
29
29
|
]);
|
|
30
30
|
const blockNumber = slot.status === "fulfilled" ? BigInt(slot.value) : 0n;
|
|
31
|
-
const
|
|
32
|
-
const
|
|
31
|
+
const nativeBalanceOk = balance.status === "fulfilled";
|
|
32
|
+
const solBalance = nativeBalanceOk ? BigInt(balance.value.value) : 0n;
|
|
33
|
+
const tokenProgramOk = tokenAccountsByOwner.status === "fulfilled";
|
|
34
|
+
const token2022ProgramOk = token2022AccountsByOwner.status === "fulfilled";
|
|
35
|
+
const walletTokenAmounts = [...tokenProgramOk ? tokenAccountsByOwner.value.value : [], ...token2022ProgramOk ? token2022AccountsByOwner.value.value : []].reduce((tokenAmounts, value) => {
|
|
33
36
|
const tokenAccount = value.account.data.parsed.info;
|
|
34
37
|
const amount = BigInt(tokenAccount.tokenAmount.amount);
|
|
35
38
|
if (amount > 0n) tokenAmounts[tokenAccount.mint] = amount;
|
|
36
39
|
return tokenAmounts;
|
|
37
40
|
}, {});
|
|
38
|
-
|
|
41
|
+
const splZeroIsKnown = tokenProgramOk && token2022ProgramOk;
|
|
39
42
|
return tokens.map((token) => {
|
|
40
|
-
if (
|
|
43
|
+
if (token.address === SolSystemProgram) {
|
|
44
|
+
if (!nativeBalanceOk) return {
|
|
45
|
+
...token,
|
|
46
|
+
blockNumber
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
...token,
|
|
50
|
+
amount: solBalance,
|
|
51
|
+
blockNumber
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const found = walletTokenAmounts[token.address];
|
|
55
|
+
if (found !== void 0) return {
|
|
41
56
|
...token,
|
|
42
|
-
amount:
|
|
57
|
+
amount: found,
|
|
58
|
+
blockNumber
|
|
59
|
+
};
|
|
60
|
+
if (splZeroIsKnown) return {
|
|
61
|
+
...token,
|
|
62
|
+
amount: 0n,
|
|
43
63
|
blockNumber
|
|
44
64
|
};
|
|
45
65
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getSolanaBalance.js","names":[],"sources":["../../../src/actions/getSolanaBalance.ts"],"sourcesContent":["import type { SDKClient } from '@lifi/sdk'\nimport {\n type ChainId,\n type Token,\n type TokenAmount,\n withDedupe,\n} from '@lifi/sdk'\nimport { address, type JsonParsedTokenAccount } from '@solana/kit'\n\nimport { callSolanaRpcsWithRetry } from '../rpc/utils.js'\n\nconst SolSystemProgram = '11111111111111111111111111111111'\nconst TokenProgramId = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'\nconst Token2022ProgramId = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'\n\nexport const getSolanaBalance = async (\n client: SDKClient,\n walletAddress: string,\n tokens: Token[]\n): Promise<TokenAmount[]> => {\n if (tokens.length === 0) {\n return []\n }\n const { chainId } = tokens[0]\n for (const token of tokens) {\n if (token.chainId !== chainId) {\n console.warn('Requested tokens have to be on the same chain.')\n }\n }\n\n return getSolanaBalanceDefault(client, chainId, tokens, walletAddress)\n}\n\nconst getSolanaBalanceDefault = async (\n client: SDKClient,\n _chainId: ChainId,\n tokens: Token[],\n walletAddress: string\n): Promise<TokenAmount[]> => {\n // Convert addresses to Solana Kit's address type\n const accountAddress = address(walletAddress)\n const tokenProgramAddress = address(TokenProgramId)\n const token2022ProgramAddress = address(Token2022ProgramId)\n\n // Use Solana Kit's RPC API with the retry wrapper\n const [slot, balance, tokenAccountsByOwner, token2022AccountsByOwner] =\n await Promise.allSettled([\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc.getSlot({ commitment: 'confirmed' }).send()\n ),\n { id: `${getSolanaBalanceDefault.name}.getSlot` }\n ),\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc.getBalance(accountAddress, { commitment: 'confirmed' }).send()\n ),\n { id: `${getSolanaBalanceDefault.name}.getBalance` }\n ),\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc\n .getTokenAccountsByOwner(\n accountAddress,\n {\n programId: tokenProgramAddress,\n },\n {\n commitment: 'confirmed',\n encoding: 'jsonParsed',\n }\n )\n .send()\n ),\n {\n id: `${getSolanaBalanceDefault.name}.getTokenAccountsByOwner.${TokenProgramId}`,\n }\n ),\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc\n .getTokenAccountsByOwner(\n accountAddress,\n {\n programId: token2022ProgramAddress,\n },\n {\n commitment: 'confirmed',\n encoding: 'jsonParsed',\n }\n )\n .send()\n ),\n {\n id: `${getSolanaBalanceDefault.name}.getTokenAccountsByOwner.${Token2022ProgramId}`,\n }\n ),\n ])\n const blockNumber = slot.status === 'fulfilled' ? BigInt(slot.value) : 0n\n const
|
|
1
|
+
{"version":3,"file":"getSolanaBalance.js","names":[],"sources":["../../../src/actions/getSolanaBalance.ts"],"sourcesContent":["import type { SDKClient } from '@lifi/sdk'\nimport {\n type ChainId,\n type Token,\n type TokenAmount,\n withDedupe,\n} from '@lifi/sdk'\nimport { address, type JsonParsedTokenAccount } from '@solana/kit'\n\nimport { callSolanaRpcsWithRetry } from '../rpc/utils.js'\n\nconst SolSystemProgram = '11111111111111111111111111111111'\nconst TokenProgramId = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'\nconst Token2022ProgramId = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'\n\nexport const getSolanaBalance = async (\n client: SDKClient,\n walletAddress: string,\n tokens: Token[]\n): Promise<TokenAmount[]> => {\n if (tokens.length === 0) {\n return []\n }\n const { chainId } = tokens[0]\n for (const token of tokens) {\n if (token.chainId !== chainId) {\n console.warn('Requested tokens have to be on the same chain.')\n }\n }\n\n return getSolanaBalanceDefault(client, chainId, tokens, walletAddress)\n}\n\nconst getSolanaBalanceDefault = async (\n client: SDKClient,\n _chainId: ChainId,\n tokens: Token[],\n walletAddress: string\n): Promise<TokenAmount[]> => {\n // Convert addresses to Solana Kit's address type\n const accountAddress = address(walletAddress)\n const tokenProgramAddress = address(TokenProgramId)\n const token2022ProgramAddress = address(Token2022ProgramId)\n\n // Use Solana Kit's RPC API with the retry wrapper\n const [slot, balance, tokenAccountsByOwner, token2022AccountsByOwner] =\n await Promise.allSettled([\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc.getSlot({ commitment: 'confirmed' }).send()\n ),\n { id: `${getSolanaBalanceDefault.name}.getSlot` }\n ),\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc.getBalance(accountAddress, { commitment: 'confirmed' }).send()\n ),\n { id: `${getSolanaBalanceDefault.name}.getBalance` }\n ),\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc\n .getTokenAccountsByOwner(\n accountAddress,\n {\n programId: tokenProgramAddress,\n },\n {\n commitment: 'confirmed',\n encoding: 'jsonParsed',\n }\n )\n .send()\n ),\n {\n id: `${getSolanaBalanceDefault.name}.getTokenAccountsByOwner.${TokenProgramId}`,\n }\n ),\n withDedupe(\n () =>\n callSolanaRpcsWithRetry(client, (rpc) =>\n rpc\n .getTokenAccountsByOwner(\n accountAddress,\n {\n programId: token2022ProgramAddress,\n },\n {\n commitment: 'confirmed',\n encoding: 'jsonParsed',\n }\n )\n .send()\n ),\n {\n id: `${getSolanaBalanceDefault.name}.getTokenAccountsByOwner.${Token2022ProgramId}`,\n }\n ),\n ])\n const blockNumber = slot.status === 'fulfilled' ? BigInt(slot.value) : 0n\n const nativeBalanceOk = balance.status === 'fulfilled'\n const solBalance = nativeBalanceOk ? BigInt(balance.value.value) : 0n\n const tokenProgramOk = tokenAccountsByOwner.status === 'fulfilled'\n const token2022ProgramOk = token2022AccountsByOwner.status === 'fulfilled'\n\n const walletTokenAmounts = [\n ...(tokenProgramOk ? tokenAccountsByOwner.value.value : []),\n ...(token2022ProgramOk ? token2022AccountsByOwner.value.value : []),\n ].reduce(\n (tokenAmounts: Record<string, bigint>, value) => {\n const tokenAccount: JsonParsedTokenAccount =\n value.account.data.parsed.info\n const amount = BigInt(tokenAccount.tokenAmount.amount)\n if (amount > 0n) {\n tokenAmounts[tokenAccount.mint] = amount\n }\n return tokenAmounts\n },\n {} as Record<string, bigint>\n )\n\n // We can only confidently report 0n for an SPL mint when both Token and\n // Token2022 program queries succeeded — otherwise the mint may live in the\n // program whose query failed (e.g. PYUSD on Token2022).\n const splZeroIsKnown = tokenProgramOk && token2022ProgramOk\n\n const tokenAmounts: TokenAmount[] = tokens.map((token) => {\n const isNative = token.address === SolSystemProgram\n if (isNative) {\n if (!nativeBalanceOk) {\n return { ...token, blockNumber }\n }\n return { ...token, amount: solBalance, blockNumber }\n }\n const found = walletTokenAmounts[token.address]\n if (found !== undefined) {\n return { ...token, amount: found, blockNumber }\n }\n if (splZeroIsKnown) {\n return { ...token, amount: 0n, blockNumber }\n }\n return { ...token, blockNumber }\n })\n return tokenAmounts\n}\n"],"mappings":";;;;AAWA,MAAM,mBAAmB;AACzB,MAAM,iBAAiB;AACvB,MAAM,qBAAqB;AAE3B,MAAa,mBAAmB,OAC9B,QACA,eACA,WAC2B;AAC3B,KAAI,OAAO,WAAW,EACpB,QAAO,EAAE;CAEX,MAAM,EAAE,YAAY,OAAO;AAC3B,MAAK,MAAM,SAAS,OAClB,KAAI,MAAM,YAAY,QACpB,SAAQ,KAAK,iDAAiD;AAIlE,QAAO,wBAAwB,QAAQ,SAAS,QAAQ,cAAc;;AAGxE,MAAM,0BAA0B,OAC9B,QACA,UACA,QACA,kBAC2B;CAE3B,MAAM,iBAAiB,QAAQ,cAAc;CAC7C,MAAM,sBAAsB,QAAQ,eAAe;CACnD,MAAM,0BAA0B,QAAQ,mBAAmB;CAG3D,MAAM,CAAC,MAAM,SAAS,sBAAsB,4BAC1C,MAAM,QAAQ,WAAW;EACvB,iBAEI,wBAAwB,SAAS,QAC/B,IAAI,QAAQ,EAAE,YAAY,aAAa,CAAC,CAAC,MAAM,CAChD,EACH,EAAE,IAAI,GAAG,wBAAwB,KAAK,WAAW,CAClD;EACD,iBAEI,wBAAwB,SAAS,QAC/B,IAAI,WAAW,gBAAgB,EAAE,YAAY,aAAa,CAAC,CAAC,MAAM,CACnE,EACH,EAAE,IAAI,GAAG,wBAAwB,KAAK,cAAc,CACrD;EACD,iBAEI,wBAAwB,SAAS,QAC/B,IACG,wBACC,gBACA,EACE,WAAW,qBACZ,EACD;GACE,YAAY;GACZ,UAAU;GACX,CACF,CACA,MAAM,CACV,EACH,EACE,IAAI,GAAG,wBAAwB,KAAK,2BAA2B,kBAChE,CACF;EACD,iBAEI,wBAAwB,SAAS,QAC/B,IACG,wBACC,gBACA,EACE,WAAW,yBACZ,EACD;GACE,YAAY;GACZ,UAAU;GACX,CACF,CACA,MAAM,CACV,EACH,EACE,IAAI,GAAG,wBAAwB,KAAK,2BAA2B,sBAChE,CACF;EACF,CAAC;CACJ,MAAM,cAAc,KAAK,WAAW,cAAc,OAAO,KAAK,MAAM,GAAG;CACvE,MAAM,kBAAkB,QAAQ,WAAW;CAC3C,MAAM,aAAa,kBAAkB,OAAO,QAAQ,MAAM,MAAM,GAAG;CACnE,MAAM,iBAAiB,qBAAqB,WAAW;CACvD,MAAM,qBAAqB,yBAAyB,WAAW;CAE/D,MAAM,qBAAqB,CACzB,GAAI,iBAAiB,qBAAqB,MAAM,QAAQ,EAAE,EAC1D,GAAI,qBAAqB,yBAAyB,MAAM,QAAQ,EAAE,CACnE,CAAC,QACC,cAAsC,UAAU;EAC/C,MAAM,eACJ,MAAM,QAAQ,KAAK,OAAO;EAC5B,MAAM,SAAS,OAAO,aAAa,YAAY,OAAO;AACtD,MAAI,SAAS,GACX,cAAa,aAAa,QAAQ;AAEpC,SAAO;IAET,EAAE,CACH;CAKD,MAAM,iBAAiB,kBAAkB;AAmBzC,QAjBoC,OAAO,KAAK,UAAU;AAExD,MADiB,MAAM,YAAY,kBACrB;AACZ,OAAI,CAAC,gBACH,QAAO;IAAE,GAAG;IAAO;IAAa;AAElC,UAAO;IAAE,GAAG;IAAO,QAAQ;IAAY;IAAa;;EAEtD,MAAM,QAAQ,mBAAmB,MAAM;AACvC,MAAI,UAAU,KAAA,EACZ,QAAO;GAAE,GAAG;GAAO,QAAQ;GAAO;GAAa;AAEjD,MAAI,eACF,QAAO;GAAE,GAAG;GAAO,QAAQ;GAAI;GAAa;AAE9C,SAAO;GAAE,GAAG;GAAO;GAAa;GAChC"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { base64ToUint8Array } from "../../utils/base64ToUint8Array.js";
|
|
2
2
|
import { getWalletFeature } from "../../utils/getWalletFeature.js";
|
|
3
|
-
import { withTimeout } from "
|
|
4
|
-
import { BaseStepExecutionTask, LiFiErrorCode, TransactionError, getTransactionRequestData } from "@lifi/sdk";
|
|
3
|
+
import { BaseStepExecutionTask, LiFiErrorCode, TransactionError, getTransactionRequestData, withTimeout } from "@lifi/sdk";
|
|
5
4
|
import { getTransactionCodec } from "@solana/kit";
|
|
6
5
|
import { SolanaSignTransaction } from "@solana/wallet-standard-features";
|
|
7
6
|
//#region src/core/tasks/SolanaSignAndExecuteTask.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SolanaSignAndExecuteTask.js","names":[],"sources":["../../../../src/core/tasks/SolanaSignAndExecuteTask.ts"],"sourcesContent":["import {\n BaseStepExecutionTask,\n getTransactionRequestData,\n LiFiErrorCode,\n type TaskResult,\n TransactionError,\n} from '@lifi/sdk'\nimport { getTransactionCodec } from '@solana/kit'\nimport { SolanaSignTransaction } from '@solana/wallet-standard-features'\nimport type { SolanaStepExecutorContext } from '../../types.js'\nimport { base64ToUint8Array } from '../../utils/base64ToUint8Array.js'\nimport { getWalletFeature } from '../../utils/getWalletFeature.js'\
|
|
1
|
+
{"version":3,"file":"SolanaSignAndExecuteTask.js","names":[],"sources":["../../../../src/core/tasks/SolanaSignAndExecuteTask.ts"],"sourcesContent":["import {\n BaseStepExecutionTask,\n getTransactionRequestData,\n LiFiErrorCode,\n type TaskResult,\n TransactionError,\n withTimeout,\n} from '@lifi/sdk'\nimport { getTransactionCodec } from '@solana/kit'\nimport { SolanaSignTransaction } from '@solana/wallet-standard-features'\nimport type { SolanaStepExecutorContext } from '../../types.js'\nimport { base64ToUint8Array } from '../../utils/base64ToUint8Array.js'\nimport { getWalletFeature } from '../../utils/getWalletFeature.js'\n\nexport class SolanaSignAndExecuteTask extends BaseStepExecutionTask {\n async run(context: SolanaStepExecutorContext): Promise<TaskResult> {\n const {\n step,\n wallet,\n walletAccount,\n statusManager,\n executionOptions,\n isBridgeExecution,\n } = context\n\n const action = statusManager.findAction(\n step,\n isBridgeExecution ? 'CROSS_CHAIN' : 'SWAP'\n )\n if (!action) {\n throw new TransactionError(\n LiFiErrorCode.TransactionUnprepared,\n 'Unable to prepare transaction. Action not found.'\n )\n }\n\n const transactionRequestData = await getTransactionRequestData(\n step,\n executionOptions\n )\n\n // Handle both single transaction (string) and multiple transactions (array)\n const transactionDataArray = Array.isArray(transactionRequestData)\n ? transactionRequestData\n : [transactionRequestData]\n\n const transactionBytesArray = transactionDataArray.map((data) =>\n base64ToUint8Array(data)\n )\n\n const signedTransactionOutputs = await withTimeout(\n async () => {\n const { signTransaction } = getWalletFeature(\n wallet,\n SolanaSignTransaction\n )\n // Spread the inputs to sign all transactions at once\n return signTransaction(\n ...transactionBytesArray.map((transaction) => ({\n account: walletAccount,\n transaction,\n }))\n )\n },\n {\n // https://solana.com/docs/advanced/confirmation#transaction-expiration\n // Use 2 minutes to account for fluctuations\n timeout: 120_000,\n errorInstance: new TransactionError(\n LiFiErrorCode.TransactionExpired,\n 'Transaction has expired: blockhash is no longer recent enough.'\n ),\n }\n )\n\n if (signedTransactionOutputs.length === 0) {\n throw new TransactionError(\n LiFiErrorCode.TransactionUnprepared,\n 'No signed transaction returned from signer.'\n )\n }\n\n statusManager.updateAction(step, action.type, 'PENDING', {\n signedAt: Date.now(),\n })\n\n const transactionCodec = getTransactionCodec()\n\n // Decode all signed transactions\n const signedTransactions = signedTransactionOutputs.map((output) =>\n transactionCodec.decode(output.signedTransaction)\n )\n\n return {\n status: 'COMPLETED',\n context: { signedTransactions },\n }\n }\n}\n"],"mappings":";;;;;;AAcA,IAAa,2BAAb,cAA8C,sBAAsB;CAClE,MAAM,IAAI,SAAyD;EACjE,MAAM,EACJ,MACA,QACA,eACA,eACA,kBACA,sBACE;EAEJ,MAAM,SAAS,cAAc,WAC3B,MACA,oBAAoB,gBAAgB,OACrC;AACD,MAAI,CAAC,OACH,OAAM,IAAI,iBACR,cAAc,uBACd,mDACD;EAGH,MAAM,yBAAyB,MAAM,0BACnC,MACA,iBACD;EAOD,MAAM,yBAJuB,MAAM,QAAQ,uBAAuB,GAC9D,yBACA,CAAC,uBAAuB,EAEuB,KAAK,SACtD,mBAAmB,KAAK,CACzB;EAED,MAAM,2BAA2B,MAAM,YACrC,YAAY;GACV,MAAM,EAAE,oBAAoB,iBAC1B,QACA,sBACD;AAED,UAAO,gBACL,GAAG,sBAAsB,KAAK,iBAAiB;IAC7C,SAAS;IACT;IACD,EAAE,CACJ;KAEH;GAGE,SAAS;GACT,eAAe,IAAI,iBACjB,cAAc,oBACd,iEACD;GACF,CACF;AAED,MAAI,yBAAyB,WAAW,EACtC,OAAM,IAAI,iBACR,cAAc,uBACd,8CACD;AAGH,gBAAc,aAAa,MAAM,OAAO,MAAM,WAAW,EACvD,UAAU,KAAK,KAAK,EACrB,CAAC;EAEF,MAAM,mBAAmB,qBAAqB;AAO9C,SAAO;GACL,QAAQ;GACR,SAAS,EAAE,oBANc,yBAAyB,KAAK,WACvD,iBAAiB,OAAO,OAAO,kBAAkB,CAClD,EAIgC;GAChC"}
|
package/dist/esm/version.d.ts
CHANGED
package/dist/esm/version.js
CHANGED
package/dist/esm/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","names":[],"sources":["../../src/version.ts"],"sourcesContent":["export const name = '@lifi/sdk-provider-solana'\nexport const version = '4.0.0-beta.
|
|
1
|
+
{"version":3,"file":"version.js","names":[],"sources":["../../src/version.ts"],"sourcesContent":["export const name = '@lifi/sdk-provider-solana'\nexport const version = '4.0.0-beta.6'\n"],"mappings":";AAAA,MAAa,OAAO;AACpB,MAAa,UAAU"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lifi/sdk-provider-solana",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.6",
|
|
4
4
|
"description": "LI.FI Solana SDK Provider for Any-to-Any Cross-Chain-Swap",
|
|
5
5
|
"homepage": "https://github.com/lifinance/sdk",
|
|
6
6
|
"bugs": {
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
"./package.json": "./package.json"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@solana/kit": "^6.
|
|
31
|
+
"@solana/kit": "^6.8.0",
|
|
32
32
|
"@solana/wallet-standard-features": "^1.3.0",
|
|
33
33
|
"@wallet-standard/base": "^1.1.0",
|
|
34
|
-
"@lifi/sdk": "4.0.0-beta.
|
|
34
|
+
"@lifi/sdk": "4.0.0-beta.6"
|
|
35
35
|
},
|
|
36
36
|
"publishConfig": {
|
|
37
37
|
"access": "public"
|
|
@@ -101,16 +101,14 @@ const getSolanaBalanceDefault = async (
|
|
|
101
101
|
),
|
|
102
102
|
])
|
|
103
103
|
const blockNumber = slot.status === 'fulfilled' ? BigInt(slot.value) : 0n
|
|
104
|
-
const
|
|
105
|
-
|
|
104
|
+
const nativeBalanceOk = balance.status === 'fulfilled'
|
|
105
|
+
const solBalance = nativeBalanceOk ? BigInt(balance.value.value) : 0n
|
|
106
|
+
const tokenProgramOk = tokenAccountsByOwner.status === 'fulfilled'
|
|
107
|
+
const token2022ProgramOk = token2022AccountsByOwner.status === 'fulfilled'
|
|
106
108
|
|
|
107
109
|
const walletTokenAmounts = [
|
|
108
|
-
...(tokenAccountsByOwner.
|
|
109
|
-
|
|
110
|
-
: []),
|
|
111
|
-
...(token2022AccountsByOwner.status === 'fulfilled'
|
|
112
|
-
? token2022AccountsByOwner.value.value
|
|
113
|
-
: []),
|
|
110
|
+
...(tokenProgramOk ? tokenAccountsByOwner.value.value : []),
|
|
111
|
+
...(token2022ProgramOk ? token2022AccountsByOwner.value.value : []),
|
|
114
112
|
].reduce(
|
|
115
113
|
(tokenAmounts: Record<string, bigint>, value) => {
|
|
116
114
|
const tokenAccount: JsonParsedTokenAccount =
|
|
@@ -124,19 +122,27 @@ const getSolanaBalanceDefault = async (
|
|
|
124
122
|
{} as Record<string, bigint>
|
|
125
123
|
)
|
|
126
124
|
|
|
127
|
-
|
|
125
|
+
// We can only confidently report 0n for an SPL mint when both Token and
|
|
126
|
+
// Token2022 program queries succeeded — otherwise the mint may live in the
|
|
127
|
+
// program whose query failed (e.g. PYUSD on Token2022).
|
|
128
|
+
const splZeroIsKnown = tokenProgramOk && token2022ProgramOk
|
|
129
|
+
|
|
128
130
|
const tokenAmounts: TokenAmount[] = tokens.map((token) => {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
blockNumber,
|
|
131
|
+
const isNative = token.address === SolSystemProgram
|
|
132
|
+
if (isNative) {
|
|
133
|
+
if (!nativeBalanceOk) {
|
|
134
|
+
return { ...token, blockNumber }
|
|
134
135
|
}
|
|
136
|
+
return { ...token, amount: solBalance, blockNumber }
|
|
137
|
+
}
|
|
138
|
+
const found = walletTokenAmounts[token.address]
|
|
139
|
+
if (found !== undefined) {
|
|
140
|
+
return { ...token, amount: found, blockNumber }
|
|
135
141
|
}
|
|
136
|
-
|
|
137
|
-
...token,
|
|
138
|
-
blockNumber,
|
|
142
|
+
if (splZeroIsKnown) {
|
|
143
|
+
return { ...token, amount: 0n, blockNumber }
|
|
139
144
|
}
|
|
145
|
+
return { ...token, blockNumber }
|
|
140
146
|
})
|
|
141
147
|
return tokenAmounts
|
|
142
148
|
}
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
LiFiErrorCode,
|
|
5
5
|
type TaskResult,
|
|
6
6
|
TransactionError,
|
|
7
|
+
withTimeout,
|
|
7
8
|
} from '@lifi/sdk'
|
|
8
9
|
import { getTransactionCodec } from '@solana/kit'
|
|
9
10
|
import { SolanaSignTransaction } from '@solana/wallet-standard-features'
|
|
10
11
|
import type { SolanaStepExecutorContext } from '../../types.js'
|
|
11
12
|
import { base64ToUint8Array } from '../../utils/base64ToUint8Array.js'
|
|
12
13
|
import { getWalletFeature } from '../../utils/getWalletFeature.js'
|
|
13
|
-
import { withTimeout } from '../../utils/withTimeout.js'
|
|
14
14
|
|
|
15
15
|
export class SolanaSignAndExecuteTask extends BaseStepExecutionTask {
|
|
16
16
|
async run(context: SolanaStepExecutorContext): Promise<TaskResult> {
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const name = '@lifi/sdk-provider-solana'
|
|
2
|
-
export const version = '4.0.0-beta.
|
|
2
|
+
export const version = '4.0.0-beta.6'
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
//#region src/utils/withTimeout.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Wraps a function in a timeout.
|
|
4
|
-
* Based on viem's withTimeout implementation.
|
|
5
|
-
* @param fn - The function to wrap.
|
|
6
|
-
* @param timeout - The timeout in milliseconds.
|
|
7
|
-
* @param errorInstance - The error instance to throw when the timeout is reached.
|
|
8
|
-
* @param signal - Whether or not the timeout should use an abort signal.
|
|
9
|
-
* @returns The result of the function.
|
|
10
|
-
*/
|
|
11
|
-
declare function withTimeout<T>(fn: ({
|
|
12
|
-
signal
|
|
13
|
-
}: {
|
|
14
|
-
signal: AbortController["signal"] | null;
|
|
15
|
-
}) => Promise<T>, {
|
|
16
|
-
errorInstance,
|
|
17
|
-
timeout,
|
|
18
|
-
signal
|
|
19
|
-
}: {
|
|
20
|
-
errorInstance?: Error | undefined;
|
|
21
|
-
timeout: number;
|
|
22
|
-
signal?: boolean | undefined;
|
|
23
|
-
}): Promise<T>;
|
|
24
|
-
//#endregion
|
|
25
|
-
export { withTimeout };
|
|
26
|
-
//# sourceMappingURL=withTimeout.d.ts.map
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
//#region src/utils/withTimeout.ts
|
|
3
|
-
/**
|
|
4
|
-
* Wraps a function in a timeout.
|
|
5
|
-
* Based on viem's withTimeout implementation.
|
|
6
|
-
* @param fn - The function to wrap.
|
|
7
|
-
* @param timeout - The timeout in milliseconds.
|
|
8
|
-
* @param errorInstance - The error instance to throw when the timeout is reached.
|
|
9
|
-
* @param signal - Whether or not the timeout should use an abort signal.
|
|
10
|
-
* @returns The result of the function.
|
|
11
|
-
*/
|
|
12
|
-
function withTimeout(fn, { errorInstance = /* @__PURE__ */ new Error("timed out"), timeout, signal }) {
|
|
13
|
-
return new Promise((resolve, reject) => {
|
|
14
|
-
(async () => {
|
|
15
|
-
let timeoutId;
|
|
16
|
-
try {
|
|
17
|
-
const controller = new AbortController();
|
|
18
|
-
if (timeout > 0) timeoutId = setTimeout(() => {
|
|
19
|
-
if (signal) controller.abort();
|
|
20
|
-
else reject(errorInstance);
|
|
21
|
-
}, timeout);
|
|
22
|
-
resolve(await fn({ signal: controller?.signal || null }));
|
|
23
|
-
} catch (err) {
|
|
24
|
-
if (err?.name === "AbortError") reject(errorInstance);
|
|
25
|
-
reject(err);
|
|
26
|
-
} finally {
|
|
27
|
-
clearTimeout(timeoutId);
|
|
28
|
-
}
|
|
29
|
-
})();
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
//#endregion
|
|
33
|
-
exports.withTimeout = withTimeout;
|
|
34
|
-
|
|
35
|
-
//# sourceMappingURL=withTimeout.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"withTimeout.js","names":[],"sources":["../../../src/utils/withTimeout.ts"],"sourcesContent":["/**\n * Wraps a function in a timeout.\n * Based on viem's withTimeout implementation.\n * @param fn - The function to wrap.\n * @param timeout - The timeout in milliseconds.\n * @param errorInstance - The error instance to throw when the timeout is reached.\n * @param signal - Whether or not the timeout should use an abort signal.\n * @returns The result of the function.\n */\nexport function withTimeout<T>(\n fn: ({ signal }: { signal: AbortController['signal'] | null }) => Promise<T>,\n {\n errorInstance = new Error('timed out'),\n timeout,\n signal,\n }: {\n // The error instance to throw when the timeout is reached.\n errorInstance?: Error | undefined\n // The timeout (in ms).\n timeout: number\n // Whether or not the timeout should use an abort signal.\n signal?: boolean | undefined\n }\n): Promise<T> {\n return new Promise((resolve, reject) => {\n ;(async () => {\n let timeoutId!: NodeJS.Timeout\n try {\n const controller = new AbortController()\n if (timeout > 0) {\n timeoutId = setTimeout(() => {\n if (signal) {\n controller.abort()\n } else {\n reject(errorInstance)\n }\n }, timeout) as NodeJS.Timeout // need to cast because bun globals.d.ts overrides @types/node\n }\n resolve(await fn({ signal: controller?.signal || null }))\n } catch (err) {\n if ((err as Error)?.name === 'AbortError') {\n reject(errorInstance)\n }\n reject(err)\n } finally {\n clearTimeout(timeoutId)\n }\n })()\n })\n}\n"],"mappings":";;;;;;;;;;;AASA,SAAgB,YACd,IACA,EACE,gCAAgB,IAAI,MAAM,YAAY,EACtC,SACA,UASU;AACZ,QAAO,IAAI,SAAS,SAAS,WAAW;AACrC,GAAC,YAAY;GACZ,IAAI;AACJ,OAAI;IACF,MAAM,aAAa,IAAI,iBAAiB;AACxC,QAAI,UAAU,EACZ,aAAY,iBAAiB;AAC3B,SAAI,OACF,YAAW,OAAO;SAElB,QAAO,cAAc;OAEtB,QAAQ;AAEb,YAAQ,MAAM,GAAG,EAAE,QAAQ,YAAY,UAAU,MAAM,CAAC,CAAC;YAClD,KAAK;AACZ,QAAK,KAAe,SAAS,aAC3B,QAAO,cAAc;AAEvB,WAAO,IAAI;aACH;AACR,iBAAa,UAAU;;MAEvB;GACJ"}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
//#region src/utils/withTimeout.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Wraps a function in a timeout.
|
|
4
|
-
* Based on viem's withTimeout implementation.
|
|
5
|
-
* @param fn - The function to wrap.
|
|
6
|
-
* @param timeout - The timeout in milliseconds.
|
|
7
|
-
* @param errorInstance - The error instance to throw when the timeout is reached.
|
|
8
|
-
* @param signal - Whether or not the timeout should use an abort signal.
|
|
9
|
-
* @returns The result of the function.
|
|
10
|
-
*/
|
|
11
|
-
declare function withTimeout<T>(fn: ({
|
|
12
|
-
signal
|
|
13
|
-
}: {
|
|
14
|
-
signal: AbortController["signal"] | null;
|
|
15
|
-
}) => Promise<T>, {
|
|
16
|
-
errorInstance,
|
|
17
|
-
timeout,
|
|
18
|
-
signal
|
|
19
|
-
}: {
|
|
20
|
-
errorInstance?: Error | undefined;
|
|
21
|
-
timeout: number;
|
|
22
|
-
signal?: boolean | undefined;
|
|
23
|
-
}): Promise<T>;
|
|
24
|
-
//#endregion
|
|
25
|
-
export { withTimeout };
|
|
26
|
-
//# sourceMappingURL=withTimeout.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"withTimeout.d.ts","names":[],"sources":["../../../src/utils/withTimeout.ts"],"mappings":";;AASA;;;;;;;;iBAAgB,WAAA,GAAA,CACd,EAAA;EAAO;AAAA;EAAY,MAAA,EAAQ,eAAA;AAAA,MAAuC,OAAA,CAAQ,CAAA;EAExE,aAAA;EACA,OAAA;EACA;AAAA;EAGA,aAAA,GAAgB,KAAA;EAEhB,OAAA;EAEA,MAAA;AAAA,IAED,OAAA,CAAQ,CAAA"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
//#region src/utils/withTimeout.ts
|
|
2
|
-
/**
|
|
3
|
-
* Wraps a function in a timeout.
|
|
4
|
-
* Based on viem's withTimeout implementation.
|
|
5
|
-
* @param fn - The function to wrap.
|
|
6
|
-
* @param timeout - The timeout in milliseconds.
|
|
7
|
-
* @param errorInstance - The error instance to throw when the timeout is reached.
|
|
8
|
-
* @param signal - Whether or not the timeout should use an abort signal.
|
|
9
|
-
* @returns The result of the function.
|
|
10
|
-
*/
|
|
11
|
-
function withTimeout(fn, { errorInstance = /* @__PURE__ */ new Error("timed out"), timeout, signal }) {
|
|
12
|
-
return new Promise((resolve, reject) => {
|
|
13
|
-
(async () => {
|
|
14
|
-
let timeoutId;
|
|
15
|
-
try {
|
|
16
|
-
const controller = new AbortController();
|
|
17
|
-
if (timeout > 0) timeoutId = setTimeout(() => {
|
|
18
|
-
if (signal) controller.abort();
|
|
19
|
-
else reject(errorInstance);
|
|
20
|
-
}, timeout);
|
|
21
|
-
resolve(await fn({ signal: controller?.signal || null }));
|
|
22
|
-
} catch (err) {
|
|
23
|
-
if (err?.name === "AbortError") reject(errorInstance);
|
|
24
|
-
reject(err);
|
|
25
|
-
} finally {
|
|
26
|
-
clearTimeout(timeoutId);
|
|
27
|
-
}
|
|
28
|
-
})();
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
//#endregion
|
|
32
|
-
export { withTimeout };
|
|
33
|
-
|
|
34
|
-
//# sourceMappingURL=withTimeout.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"withTimeout.js","names":[],"sources":["../../../src/utils/withTimeout.ts"],"sourcesContent":["/**\n * Wraps a function in a timeout.\n * Based on viem's withTimeout implementation.\n * @param fn - The function to wrap.\n * @param timeout - The timeout in milliseconds.\n * @param errorInstance - The error instance to throw when the timeout is reached.\n * @param signal - Whether or not the timeout should use an abort signal.\n * @returns The result of the function.\n */\nexport function withTimeout<T>(\n fn: ({ signal }: { signal: AbortController['signal'] | null }) => Promise<T>,\n {\n errorInstance = new Error('timed out'),\n timeout,\n signal,\n }: {\n // The error instance to throw when the timeout is reached.\n errorInstance?: Error | undefined\n // The timeout (in ms).\n timeout: number\n // Whether or not the timeout should use an abort signal.\n signal?: boolean | undefined\n }\n): Promise<T> {\n return new Promise((resolve, reject) => {\n ;(async () => {\n let timeoutId!: NodeJS.Timeout\n try {\n const controller = new AbortController()\n if (timeout > 0) {\n timeoutId = setTimeout(() => {\n if (signal) {\n controller.abort()\n } else {\n reject(errorInstance)\n }\n }, timeout) as NodeJS.Timeout // need to cast because bun globals.d.ts overrides @types/node\n }\n resolve(await fn({ signal: controller?.signal || null }))\n } catch (err) {\n if ((err as Error)?.name === 'AbortError') {\n reject(errorInstance)\n }\n reject(err)\n } finally {\n clearTimeout(timeoutId)\n }\n })()\n })\n}\n"],"mappings":";;;;;;;;;;AASA,SAAgB,YACd,IACA,EACE,gCAAgB,IAAI,MAAM,YAAY,EACtC,SACA,UASU;AACZ,QAAO,IAAI,SAAS,SAAS,WAAW;AACrC,GAAC,YAAY;GACZ,IAAI;AACJ,OAAI;IACF,MAAM,aAAa,IAAI,iBAAiB;AACxC,QAAI,UAAU,EACZ,aAAY,iBAAiB;AAC3B,SAAI,OACF,YAAW,OAAO;SAElB,QAAO,cAAc;OAEtB,QAAQ;AAEb,YAAQ,MAAM,GAAG,EAAE,QAAQ,YAAY,UAAU,MAAM,CAAC,CAAC;YAClD,KAAK;AACZ,QAAK,KAAe,SAAS,aAC3B,QAAO,cAAc;AAEvB,WAAO,IAAI;aACH;AACR,iBAAa,UAAU;;MAEvB;GACJ"}
|
package/src/utils/withTimeout.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Wraps a function in a timeout.
|
|
3
|
-
* Based on viem's withTimeout implementation.
|
|
4
|
-
* @param fn - The function to wrap.
|
|
5
|
-
* @param timeout - The timeout in milliseconds.
|
|
6
|
-
* @param errorInstance - The error instance to throw when the timeout is reached.
|
|
7
|
-
* @param signal - Whether or not the timeout should use an abort signal.
|
|
8
|
-
* @returns The result of the function.
|
|
9
|
-
*/
|
|
10
|
-
export function withTimeout<T>(
|
|
11
|
-
fn: ({ signal }: { signal: AbortController['signal'] | null }) => Promise<T>,
|
|
12
|
-
{
|
|
13
|
-
errorInstance = new Error('timed out'),
|
|
14
|
-
timeout,
|
|
15
|
-
signal,
|
|
16
|
-
}: {
|
|
17
|
-
// The error instance to throw when the timeout is reached.
|
|
18
|
-
errorInstance?: Error | undefined
|
|
19
|
-
// The timeout (in ms).
|
|
20
|
-
timeout: number
|
|
21
|
-
// Whether or not the timeout should use an abort signal.
|
|
22
|
-
signal?: boolean | undefined
|
|
23
|
-
}
|
|
24
|
-
): Promise<T> {
|
|
25
|
-
return new Promise((resolve, reject) => {
|
|
26
|
-
;(async () => {
|
|
27
|
-
let timeoutId!: NodeJS.Timeout
|
|
28
|
-
try {
|
|
29
|
-
const controller = new AbortController()
|
|
30
|
-
if (timeout > 0) {
|
|
31
|
-
timeoutId = setTimeout(() => {
|
|
32
|
-
if (signal) {
|
|
33
|
-
controller.abort()
|
|
34
|
-
} else {
|
|
35
|
-
reject(errorInstance)
|
|
36
|
-
}
|
|
37
|
-
}, timeout) as NodeJS.Timeout // need to cast because bun globals.d.ts overrides @types/node
|
|
38
|
-
}
|
|
39
|
-
resolve(await fn({ signal: controller?.signal || null }))
|
|
40
|
-
} catch (err) {
|
|
41
|
-
if ((err as Error)?.name === 'AbortError') {
|
|
42
|
-
reject(errorInstance)
|
|
43
|
-
}
|
|
44
|
-
reject(err)
|
|
45
|
-
} finally {
|
|
46
|
-
clearTimeout(timeoutId)
|
|
47
|
-
}
|
|
48
|
-
})()
|
|
49
|
-
})
|
|
50
|
-
}
|