@t2000/sdk 1.5.0 → 1.6.0
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/adapters/index.cjs +4 -1
- package/dist/adapters/index.cjs.map +1 -1
- package/dist/adapters/index.js +4 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/browser.cjs +2 -1
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +2 -1
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +501 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +523 -4
- package/dist/index.d.ts +523 -4
- package/dist/index.js +490 -7
- package/dist/index.js.map +1 -1
- package/dist/{types-BhiUiiNs.d.ts → types-B0VlW8Ov.d.ts} +75 -1
- package/dist/{types-CMVkJNFp.d.cts → types-DrHllxZ5.d.cts} +75 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -143,6 +143,32 @@ var init_errors = __esm({
|
|
|
143
143
|
});
|
|
144
144
|
|
|
145
145
|
// src/token-registry.ts
|
|
146
|
+
var token_registry_exports = {};
|
|
147
|
+
__export(token_registry_exports, {
|
|
148
|
+
COIN_REGISTRY: () => COIN_REGISTRY,
|
|
149
|
+
ETH_TYPE: () => ETH_TYPE,
|
|
150
|
+
IKA_TYPE: () => IKA_TYPE,
|
|
151
|
+
LOFI_TYPE: () => LOFI_TYPE,
|
|
152
|
+
MANIFEST_TYPE: () => MANIFEST_TYPE,
|
|
153
|
+
NAVX_TYPE: () => NAVX_TYPE,
|
|
154
|
+
SUI_TYPE: () => SUI_TYPE,
|
|
155
|
+
TOKEN_MAP: () => TOKEN_MAP,
|
|
156
|
+
USDC_TYPE: () => USDC_TYPE,
|
|
157
|
+
USDE_TYPE: () => USDE_TYPE,
|
|
158
|
+
USDSUI_TYPE: () => USDSUI_TYPE,
|
|
159
|
+
USDT_TYPE: () => USDT_TYPE,
|
|
160
|
+
WAL_TYPE: () => WAL_TYPE,
|
|
161
|
+
WBTC_TYPE: () => WBTC_TYPE,
|
|
162
|
+
getCoinMeta: () => getCoinMeta,
|
|
163
|
+
getDecimalsForCoinType: () => getDecimalsForCoinType,
|
|
164
|
+
getTier: () => getTier,
|
|
165
|
+
isInRegistry: () => isInRegistry,
|
|
166
|
+
isSupported: () => isSupported,
|
|
167
|
+
isTier1: () => isTier1,
|
|
168
|
+
isTier2: () => isTier2,
|
|
169
|
+
resolveSymbol: () => resolveSymbol,
|
|
170
|
+
resolveTokenType: () => resolveTokenType
|
|
171
|
+
});
|
|
146
172
|
function getCoinMeta(coinType) {
|
|
147
173
|
return BY_TYPE.get(coinType);
|
|
148
174
|
}
|
|
@@ -626,6 +652,8 @@ __export(volo_exports, {
|
|
|
626
652
|
VOLO_PKG: () => VOLO_PKG,
|
|
627
653
|
VOLO_POOL: () => VOLO_POOL,
|
|
628
654
|
VSUI_TYPE: () => VSUI_TYPE,
|
|
655
|
+
addStakeVSuiToTx: () => addStakeVSuiToTx,
|
|
656
|
+
addUnstakeVSuiToTx: () => addUnstakeVSuiToTx,
|
|
629
657
|
buildStakeVSuiTx: () => buildStakeVSuiTx,
|
|
630
658
|
buildUnstakeVSuiTx: () => buildUnstakeVSuiTx,
|
|
631
659
|
getVoloStats: () => getVoloStats
|
|
@@ -665,7 +693,7 @@ async function buildStakeVSuiTx(_client, address, amountMist) {
|
|
|
665
693
|
return tx;
|
|
666
694
|
}
|
|
667
695
|
async function buildUnstakeVSuiTx(client, address, amountMist) {
|
|
668
|
-
const coins = await
|
|
696
|
+
const coins = await fetchCoinsByType(client, address, VSUI_TYPE);
|
|
669
697
|
if (coins.length === 0) {
|
|
670
698
|
throw new Error("No vSUI found in wallet.");
|
|
671
699
|
}
|
|
@@ -693,14 +721,81 @@ async function buildUnstakeVSuiTx(client, address, amountMist) {
|
|
|
693
721
|
tx.transferObjects([suiCoin], address);
|
|
694
722
|
return tx;
|
|
695
723
|
}
|
|
696
|
-
async function
|
|
724
|
+
async function addStakeVSuiToTx(tx, client, address, input) {
|
|
725
|
+
if (input.amountMist < MIN_STAKE_MIST) {
|
|
726
|
+
throw new Error(`Minimum stake is 1 SUI (${MIN_STAKE_MIST} MIST). Got: ${input.amountMist}`);
|
|
727
|
+
}
|
|
728
|
+
let suiCoin;
|
|
729
|
+
if (input.inputCoin) {
|
|
730
|
+
suiCoin = input.inputCoin;
|
|
731
|
+
} else {
|
|
732
|
+
const coins = await fetchCoinsByType(client, address, SUI_TYPE);
|
|
733
|
+
if (coins.length === 0) {
|
|
734
|
+
throw new Error("No SUI coins found in wallet");
|
|
735
|
+
}
|
|
736
|
+
const totalBalance = coins.reduce((sum, c) => sum + BigInt(c.balance), 0n);
|
|
737
|
+
if (totalBalance < input.amountMist) {
|
|
738
|
+
throw new Error(`Insufficient SUI: need ${input.amountMist} MIST, have ${totalBalance}`);
|
|
739
|
+
}
|
|
740
|
+
const primary = tx.object(coins[0].coinObjectId);
|
|
741
|
+
if (coins.length > 1) {
|
|
742
|
+
tx.mergeCoins(primary, coins.slice(1).map((c) => tx.object(c.coinObjectId)));
|
|
743
|
+
}
|
|
744
|
+
[suiCoin] = tx.splitCoins(primary, [input.amountMist]);
|
|
745
|
+
}
|
|
746
|
+
const [vSuiCoin] = tx.moveCall({
|
|
747
|
+
target: `${VOLO_PKG}::stake_pool::stake`,
|
|
748
|
+
arguments: [
|
|
749
|
+
tx.object(VOLO_POOL),
|
|
750
|
+
tx.object(VOLO_METADATA),
|
|
751
|
+
tx.object(SUI_SYSTEM_STATE),
|
|
752
|
+
suiCoin
|
|
753
|
+
]
|
|
754
|
+
});
|
|
755
|
+
return { coin: vSuiCoin, effectiveAmountMist: input.amountMist };
|
|
756
|
+
}
|
|
757
|
+
async function addUnstakeVSuiToTx(tx, client, address, input) {
|
|
758
|
+
let vSuiCoin;
|
|
759
|
+
if (input.inputCoin) {
|
|
760
|
+
if (input.amountMist === "all") {
|
|
761
|
+
vSuiCoin = input.inputCoin;
|
|
762
|
+
} else {
|
|
763
|
+
[vSuiCoin] = tx.splitCoins(input.inputCoin, [input.amountMist]);
|
|
764
|
+
}
|
|
765
|
+
} else {
|
|
766
|
+
const coins = await fetchCoinsByType(client, address, VSUI_TYPE);
|
|
767
|
+
if (coins.length === 0) {
|
|
768
|
+
throw new Error("No vSUI found in wallet.");
|
|
769
|
+
}
|
|
770
|
+
const primary = tx.object(coins[0].coinObjectId);
|
|
771
|
+
if (coins.length > 1) {
|
|
772
|
+
tx.mergeCoins(primary, coins.slice(1).map((c) => tx.object(c.coinObjectId)));
|
|
773
|
+
}
|
|
774
|
+
if (input.amountMist === "all") {
|
|
775
|
+
vSuiCoin = primary;
|
|
776
|
+
} else {
|
|
777
|
+
[vSuiCoin] = tx.splitCoins(primary, [input.amountMist]);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
const [suiCoin] = tx.moveCall({
|
|
781
|
+
target: `${VOLO_PKG}::stake_pool::unstake`,
|
|
782
|
+
arguments: [
|
|
783
|
+
tx.object(VOLO_POOL),
|
|
784
|
+
tx.object(VOLO_METADATA),
|
|
785
|
+
tx.object(SUI_SYSTEM_STATE),
|
|
786
|
+
vSuiCoin
|
|
787
|
+
]
|
|
788
|
+
});
|
|
789
|
+
return { coin: suiCoin, effectiveAmountMist: input.amountMist };
|
|
790
|
+
}
|
|
791
|
+
async function fetchCoinsByType(client, owner, coinType) {
|
|
697
792
|
const all = [];
|
|
698
793
|
let cursor;
|
|
699
794
|
let hasNext = true;
|
|
700
795
|
while (hasNext) {
|
|
701
796
|
const page = await client.getCoins({
|
|
702
|
-
owner
|
|
703
|
-
coinType
|
|
797
|
+
owner,
|
|
798
|
+
coinType,
|
|
704
799
|
cursor: cursor ?? void 0
|
|
705
800
|
});
|
|
706
801
|
all.push(...page.data.map((c) => ({ coinObjectId: c.coinObjectId, balance: c.balance })));
|
|
@@ -712,6 +807,7 @@ async function fetchVSuiCoins(client, address) {
|
|
|
712
807
|
var VOLO_PKG, VOLO_POOL, VOLO_METADATA, VSUI_TYPE, SUI_SYSTEM_STATE, MIN_STAKE_MIST, VOLO_STATS_URL;
|
|
713
808
|
var init_volo = __esm({
|
|
714
809
|
"src/protocols/volo.ts"() {
|
|
810
|
+
init_token_registry();
|
|
715
811
|
VOLO_PKG = "0x68d22cf8bdbcd11ecba1e094922873e4080d4d11133e2443fddda0bfd11dae20";
|
|
716
812
|
VOLO_POOL = "0x2d914e23d82fedef1b5f56a32d5c64bdcc3087ccfea2b4d6ea51a71f587840e5";
|
|
717
813
|
VOLO_METADATA = "0x680cd26af32b2bde8d3361e804c53ec1d1cfe24c7f039eb7f549e8dfde389a60";
|
|
@@ -727,6 +823,7 @@ var cetus_swap_exports = {};
|
|
|
727
823
|
__export(cetus_swap_exports, {
|
|
728
824
|
OVERLAY_FEE_RATE: () => OVERLAY_FEE_RATE,
|
|
729
825
|
TOKEN_MAP: () => TOKEN_MAP,
|
|
826
|
+
addSwapToTx: () => addSwapToTx,
|
|
730
827
|
buildSwapTx: () => buildSwapTx,
|
|
731
828
|
findSwapRoute: () => findSwapRoute,
|
|
732
829
|
resolveTokenType: () => resolveTokenType,
|
|
@@ -752,7 +849,8 @@ async function findSwapRoute(params) {
|
|
|
752
849
|
from: params.from,
|
|
753
850
|
target: params.to,
|
|
754
851
|
amount: params.amount.toString(),
|
|
755
|
-
byAmountIn: params.byAmountIn
|
|
852
|
+
byAmountIn: params.byAmountIn,
|
|
853
|
+
...params.providers ? { providers: params.providers } : {}
|
|
756
854
|
};
|
|
757
855
|
const routerData = await client.findRouters(findParams);
|
|
758
856
|
if (!routerData) return null;
|
|
@@ -794,6 +892,85 @@ async function buildSwapTx(params) {
|
|
|
794
892
|
});
|
|
795
893
|
return outputCoin;
|
|
796
894
|
}
|
|
895
|
+
async function addSwapToTx(tx, client, address, input) {
|
|
896
|
+
const { T2000Error: T2000Error2 } = await Promise.resolve().then(() => (init_errors(), errors_exports));
|
|
897
|
+
const fromType = resolveTokenType(input.from);
|
|
898
|
+
const toType = resolveTokenType(input.to);
|
|
899
|
+
if (!fromType) throw new T2000Error2("ASSET_NOT_SUPPORTED", `Unknown token: ${input.from}. Provide the symbol (USDC, SUI, ...) or full coin type.`);
|
|
900
|
+
if (!toType) throw new T2000Error2("ASSET_NOT_SUPPORTED", `Unknown token: ${input.to}. Provide the symbol (USDC, SUI, ...) or full coin type.`);
|
|
901
|
+
if (fromType === toType) throw new T2000Error2("SWAP_FAILED", "Cannot swap a token to itself");
|
|
902
|
+
if (!Number.isFinite(input.amount) || input.amount <= 0) {
|
|
903
|
+
throw new T2000Error2("INVALID_AMOUNT", "Amount must be greater than zero");
|
|
904
|
+
}
|
|
905
|
+
const fromDecimals = getDecimalsForCoinType(fromType);
|
|
906
|
+
const toDecimals = getDecimalsForCoinType(toType);
|
|
907
|
+
const requestedRaw = BigInt(Math.floor(input.amount * 10 ** fromDecimals));
|
|
908
|
+
const slippage = Math.max(1e-3, Math.min(input.slippage ?? 0.01, 0.05));
|
|
909
|
+
const byAmountIn = input.byAmountIn ?? true;
|
|
910
|
+
let inputCoin;
|
|
911
|
+
let effectiveRaw;
|
|
912
|
+
if (input.inputCoin) {
|
|
913
|
+
inputCoin = input.inputCoin;
|
|
914
|
+
effectiveRaw = requestedRaw;
|
|
915
|
+
} else {
|
|
916
|
+
const { ids, totalBalance } = await fetchAllCoinsForSwap(client, address, fromType);
|
|
917
|
+
if (ids.length === 0) {
|
|
918
|
+
throw new T2000Error2("INSUFFICIENT_BALANCE", `No ${input.from} coins found in wallet`);
|
|
919
|
+
}
|
|
920
|
+
const swapAll = requestedRaw >= totalBalance;
|
|
921
|
+
effectiveRaw = swapAll ? totalBalance : requestedRaw;
|
|
922
|
+
const primary = tx.object(ids[0]);
|
|
923
|
+
if (ids.length > 1) {
|
|
924
|
+
tx.mergeCoins(primary, ids.slice(1).map((id) => tx.object(id)));
|
|
925
|
+
}
|
|
926
|
+
inputCoin = swapAll ? primary : tx.splitCoins(primary, [effectiveRaw])[0];
|
|
927
|
+
}
|
|
928
|
+
const route = await findSwapRoute({
|
|
929
|
+
walletAddress: address,
|
|
930
|
+
from: fromType,
|
|
931
|
+
to: toType,
|
|
932
|
+
amount: effectiveRaw,
|
|
933
|
+
byAmountIn,
|
|
934
|
+
overlayFee: input.overlayFee,
|
|
935
|
+
providers: input.providers
|
|
936
|
+
});
|
|
937
|
+
if (!route) {
|
|
938
|
+
throw new T2000Error2("SWAP_NO_ROUTE", `No swap route found for ${input.from} \u2192 ${input.to}`);
|
|
939
|
+
}
|
|
940
|
+
if (route.insufficientLiquidity) {
|
|
941
|
+
throw new T2000Error2("SWAP_NO_ROUTE", `Insufficient liquidity for ${input.from} \u2192 ${input.to}`);
|
|
942
|
+
}
|
|
943
|
+
const outputCoin = await buildSwapTx({
|
|
944
|
+
walletAddress: address,
|
|
945
|
+
route,
|
|
946
|
+
tx,
|
|
947
|
+
inputCoin,
|
|
948
|
+
slippage,
|
|
949
|
+
overlayFee: input.overlayFee
|
|
950
|
+
});
|
|
951
|
+
return {
|
|
952
|
+
coin: outputCoin,
|
|
953
|
+
effectiveAmountIn: Number(effectiveRaw) / 10 ** fromDecimals,
|
|
954
|
+
expectedAmountOut: Number(route.amountOut) / 10 ** toDecimals,
|
|
955
|
+
route
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
async function fetchAllCoinsForSwap(client, owner, coinType) {
|
|
959
|
+
const ids = [];
|
|
960
|
+
let totalBalance = 0n;
|
|
961
|
+
let cursor;
|
|
962
|
+
let hasNext = true;
|
|
963
|
+
while (hasNext) {
|
|
964
|
+
const page = await client.getCoins({ owner, coinType, cursor: cursor ?? void 0 });
|
|
965
|
+
for (const c of page.data) {
|
|
966
|
+
ids.push(c.coinObjectId);
|
|
967
|
+
totalBalance += BigInt(c.balance);
|
|
968
|
+
}
|
|
969
|
+
cursor = page.nextCursor;
|
|
970
|
+
hasNext = page.hasNextPage;
|
|
971
|
+
}
|
|
972
|
+
return { ids, totalBalance };
|
|
973
|
+
}
|
|
797
974
|
async function simulateSwap(params) {
|
|
798
975
|
const client = getClient(params.walletAddress, params.overlayFee);
|
|
799
976
|
try {
|
|
@@ -806,6 +983,7 @@ async function simulateSwap(params) {
|
|
|
806
983
|
var OVERLAY_FEE_RATE, clientCache;
|
|
807
984
|
var init_cetus_swap = __esm({
|
|
808
985
|
"src/protocols/cetus-swap.ts"() {
|
|
986
|
+
init_token_registry();
|
|
809
987
|
init_token_registry();
|
|
810
988
|
OVERLAY_FEE_RATE = 1e-3;
|
|
811
989
|
clientCache = /* @__PURE__ */ new Map();
|
|
@@ -1171,6 +1349,10 @@ async function buildSendTx({
|
|
|
1171
1349
|
}
|
|
1172
1350
|
return tx;
|
|
1173
1351
|
}
|
|
1352
|
+
function addSendToTx(tx, coin, recipient) {
|
|
1353
|
+
const validRecipient = validateAddress(recipient);
|
|
1354
|
+
tx.transferObjects([coin], validRecipient);
|
|
1355
|
+
}
|
|
1174
1356
|
|
|
1175
1357
|
// src/wallet/balance.ts
|
|
1176
1358
|
var SUI_PRICE_FALLBACK = 1;
|
|
@@ -5313,7 +5495,10 @@ async function addSaveToTx(tx, _client, _address, coin, options = {}) {
|
|
|
5313
5495
|
async function addRepayToTx(tx, client, address, coin, options = {}) {
|
|
5314
5496
|
const asset = options.asset ?? "USDC";
|
|
5315
5497
|
const assetInfo = resolveAssetInfo(asset);
|
|
5316
|
-
await refreshOracle(tx, client, address, {
|
|
5498
|
+
await refreshOracle(tx, client, address, {
|
|
5499
|
+
skipPythUpdate: options.skipPythUpdate,
|
|
5500
|
+
skipOracle: options.skipOracle
|
|
5501
|
+
});
|
|
5317
5502
|
try {
|
|
5318
5503
|
await xe(tx, assetInfo.type, coin, { env: "prod" });
|
|
5319
5504
|
} catch (err) {
|
|
@@ -5457,6 +5642,12 @@ async function addClaimRewardsToTx(tx, client, address) {
|
|
|
5457
5642
|
return [];
|
|
5458
5643
|
}
|
|
5459
5644
|
}
|
|
5645
|
+
async function buildClaimRewardsTx(client, address) {
|
|
5646
|
+
const tx = new Transaction();
|
|
5647
|
+
tx.setSender(address);
|
|
5648
|
+
const rewards = await addClaimRewardsToTx(tx, client, address);
|
|
5649
|
+
return { tx, rewards };
|
|
5650
|
+
}
|
|
5460
5651
|
function aggregateClaimableRewards(claimable) {
|
|
5461
5652
|
const aggregated = /* @__PURE__ */ new Map();
|
|
5462
5653
|
for (const c of claimable) {
|
|
@@ -7188,6 +7379,298 @@ var T2000 = class _T2000 extends EventEmitter {
|
|
|
7188
7379
|
// src/index.ts
|
|
7189
7380
|
init_errors();
|
|
7190
7381
|
|
|
7382
|
+
// src/wallet/coinSelection.ts
|
|
7383
|
+
init_errors();
|
|
7384
|
+
async function fetchAllCoins(client, owner, coinType) {
|
|
7385
|
+
const ids = [];
|
|
7386
|
+
let totalBalance = 0n;
|
|
7387
|
+
let cursor;
|
|
7388
|
+
let hasNext = true;
|
|
7389
|
+
while (hasNext) {
|
|
7390
|
+
const page = await client.getCoins({ owner, coinType, cursor: cursor ?? void 0 });
|
|
7391
|
+
for (const c of page.data) {
|
|
7392
|
+
ids.push(c.coinObjectId);
|
|
7393
|
+
totalBalance += BigInt(c.balance);
|
|
7394
|
+
}
|
|
7395
|
+
cursor = page.nextCursor;
|
|
7396
|
+
hasNext = page.hasNextPage;
|
|
7397
|
+
}
|
|
7398
|
+
return { ids, totalBalance };
|
|
7399
|
+
}
|
|
7400
|
+
async function selectAndSplitCoin(tx, client, owner, coinType, amount, options = {}) {
|
|
7401
|
+
const { ids, totalBalance } = await fetchAllCoins(client, owner, coinType);
|
|
7402
|
+
if (ids.length === 0) {
|
|
7403
|
+
throw new T2000Error("INSUFFICIENT_BALANCE", `No coins found for ${coinType}`);
|
|
7404
|
+
}
|
|
7405
|
+
const allowSwapAll = options.allowSwapAll ?? true;
|
|
7406
|
+
if (amount !== "all" && amount > totalBalance && !allowSwapAll) {
|
|
7407
|
+
throw new T2000Error("INSUFFICIENT_BALANCE", `Insufficient balance for ${coinType}`, {
|
|
7408
|
+
available: totalBalance.toString(),
|
|
7409
|
+
required: amount.toString()
|
|
7410
|
+
});
|
|
7411
|
+
}
|
|
7412
|
+
const requested = amount === "all" ? totalBalance : amount;
|
|
7413
|
+
const swapAll = amount === "all" || requested >= totalBalance;
|
|
7414
|
+
const effectiveAmount = swapAll ? totalBalance : requested;
|
|
7415
|
+
const primary = tx.object(ids[0]);
|
|
7416
|
+
if (ids.length > 1) {
|
|
7417
|
+
tx.mergeCoins(primary, ids.slice(1).map((id) => tx.object(id)));
|
|
7418
|
+
}
|
|
7419
|
+
const coin = swapAll ? primary : tx.splitCoins(primary, [effectiveAmount])[0];
|
|
7420
|
+
return { coin, effectiveAmount, swapAll };
|
|
7421
|
+
}
|
|
7422
|
+
async function selectSuiCoin(tx, client, owner, amountMist, sponsoredContext) {
|
|
7423
|
+
if (sponsoredContext) {
|
|
7424
|
+
const { SUI_TYPE: SUI_TYPE2 } = await Promise.resolve().then(() => (init_token_registry(), token_registry_exports));
|
|
7425
|
+
return selectAndSplitCoin(tx, client, owner, SUI_TYPE2, amountMist);
|
|
7426
|
+
}
|
|
7427
|
+
const [coin] = tx.splitCoins(tx.gas, [amountMist]);
|
|
7428
|
+
return { coin, effectiveAmount: amountMist, swapAll: false };
|
|
7429
|
+
}
|
|
7430
|
+
init_cetus_swap();
|
|
7431
|
+
init_volo();
|
|
7432
|
+
init_token_registry();
|
|
7433
|
+
init_errors();
|
|
7434
|
+
var SPONSORED_PYTH_DEPENDENT_PROVIDERS = [
|
|
7435
|
+
"HAEDALPMM",
|
|
7436
|
+
"METASTABLE",
|
|
7437
|
+
"OBRIC",
|
|
7438
|
+
"STEAMM_OMM",
|
|
7439
|
+
"STEAMM_OMM_V2",
|
|
7440
|
+
"SEVENK",
|
|
7441
|
+
"HAEDALHMMV2"
|
|
7442
|
+
];
|
|
7443
|
+
async function getSponsoredSwapProviders() {
|
|
7444
|
+
const { getProvidersExcluding } = await import('@cetusprotocol/aggregator-sdk');
|
|
7445
|
+
return getProvidersExcluding([...SPONSORED_PYTH_DEPENDENT_PROVIDERS]);
|
|
7446
|
+
}
|
|
7447
|
+
function resolveSaveableAsset(asset) {
|
|
7448
|
+
if (!asset) return "USDC";
|
|
7449
|
+
if (asset !== "USDC" && asset !== "USDsui") {
|
|
7450
|
+
throw new T2000Error("ASSET_NOT_SUPPORTED", `Saveable asset must be USDC or USDsui, got ${asset}`);
|
|
7451
|
+
}
|
|
7452
|
+
return asset;
|
|
7453
|
+
}
|
|
7454
|
+
var WRITE_APPENDER_REGISTRY = {
|
|
7455
|
+
save_deposit: async (tx, input, ctx) => {
|
|
7456
|
+
const asset = resolveSaveableAsset(input.asset);
|
|
7457
|
+
const assetInfo = SUPPORTED_ASSETS[asset];
|
|
7458
|
+
if (input.amount <= 0) {
|
|
7459
|
+
throw new T2000Error("INVALID_AMOUNT", "Save amount must be greater than zero");
|
|
7460
|
+
}
|
|
7461
|
+
const rawAmount = BigInt(Math.floor(input.amount * 10 ** assetInfo.decimals));
|
|
7462
|
+
const { coin, effectiveAmount } = await selectAndSplitCoin(
|
|
7463
|
+
tx,
|
|
7464
|
+
ctx.client,
|
|
7465
|
+
ctx.sender,
|
|
7466
|
+
assetInfo.type,
|
|
7467
|
+
rawAmount
|
|
7468
|
+
);
|
|
7469
|
+
await addSaveToTx(tx, ctx.client, ctx.sender, coin, { asset });
|
|
7470
|
+
return {
|
|
7471
|
+
toolName: "save_deposit",
|
|
7472
|
+
effectiveAmount: Number(effectiveAmount) / 10 ** assetInfo.decimals,
|
|
7473
|
+
asset
|
|
7474
|
+
};
|
|
7475
|
+
},
|
|
7476
|
+
withdraw: async (tx, input, ctx) => {
|
|
7477
|
+
const asset = resolveSaveableAsset(input.asset);
|
|
7478
|
+
if (input.amount <= 0) {
|
|
7479
|
+
throw new T2000Error("INVALID_AMOUNT", "Withdraw amount must be greater than zero");
|
|
7480
|
+
}
|
|
7481
|
+
const { coin, effectiveAmount } = await addWithdrawToTx(
|
|
7482
|
+
tx,
|
|
7483
|
+
ctx.client,
|
|
7484
|
+
ctx.sender,
|
|
7485
|
+
input.amount,
|
|
7486
|
+
{ asset, skipPythUpdate: ctx.sponsoredContext }
|
|
7487
|
+
);
|
|
7488
|
+
tx.transferObjects([coin], ctx.sender);
|
|
7489
|
+
return { toolName: "withdraw", effectiveAmount, asset };
|
|
7490
|
+
},
|
|
7491
|
+
borrow: async (tx, input, ctx) => {
|
|
7492
|
+
const asset = resolveSaveableAsset(input.asset);
|
|
7493
|
+
if (input.amount <= 0) {
|
|
7494
|
+
throw new T2000Error("INVALID_AMOUNT", "Borrow amount must be greater than zero");
|
|
7495
|
+
}
|
|
7496
|
+
const coin = await addBorrowToTx(
|
|
7497
|
+
tx,
|
|
7498
|
+
ctx.client,
|
|
7499
|
+
ctx.sender,
|
|
7500
|
+
input.amount,
|
|
7501
|
+
{ asset, skipPythUpdate: ctx.sponsoredContext }
|
|
7502
|
+
);
|
|
7503
|
+
tx.transferObjects([coin], ctx.sender);
|
|
7504
|
+
return { toolName: "borrow", effectiveAmount: input.amount, asset };
|
|
7505
|
+
},
|
|
7506
|
+
repay_debt: async (tx, input, ctx) => {
|
|
7507
|
+
const asset = resolveSaveableAsset(input.asset);
|
|
7508
|
+
const assetInfo = SUPPORTED_ASSETS[asset];
|
|
7509
|
+
if (input.amount <= 0) {
|
|
7510
|
+
throw new T2000Error("INVALID_AMOUNT", "Repay amount must be greater than zero");
|
|
7511
|
+
}
|
|
7512
|
+
const rawAmount = BigInt(Math.floor(input.amount * 10 ** assetInfo.decimals));
|
|
7513
|
+
const { coin, effectiveAmount } = await selectAndSplitCoin(
|
|
7514
|
+
tx,
|
|
7515
|
+
ctx.client,
|
|
7516
|
+
ctx.sender,
|
|
7517
|
+
assetInfo.type,
|
|
7518
|
+
rawAmount
|
|
7519
|
+
);
|
|
7520
|
+
await addRepayToTx(tx, ctx.client, ctx.sender, coin, {
|
|
7521
|
+
asset,
|
|
7522
|
+
skipOracle: ctx.sponsoredContext
|
|
7523
|
+
});
|
|
7524
|
+
return {
|
|
7525
|
+
toolName: "repay_debt",
|
|
7526
|
+
effectiveAmount: Number(effectiveAmount) / 10 ** assetInfo.decimals,
|
|
7527
|
+
asset
|
|
7528
|
+
};
|
|
7529
|
+
},
|
|
7530
|
+
send_transfer: async (tx, input, ctx) => {
|
|
7531
|
+
const recipient = validateAddress(input.to);
|
|
7532
|
+
const asset = input.asset ?? "USDC";
|
|
7533
|
+
const assetInfo = SUPPORTED_ASSETS[asset];
|
|
7534
|
+
if (!assetInfo) {
|
|
7535
|
+
throw new T2000Error("ASSET_NOT_SUPPORTED", `Asset ${asset} is not supported`);
|
|
7536
|
+
}
|
|
7537
|
+
if (input.amount <= 0) {
|
|
7538
|
+
throw new T2000Error("INVALID_AMOUNT", "Send amount must be greater than zero");
|
|
7539
|
+
}
|
|
7540
|
+
const rawAmount = BigInt(Math.floor(input.amount * 10 ** assetInfo.decimals));
|
|
7541
|
+
let coin;
|
|
7542
|
+
let effectiveRaw;
|
|
7543
|
+
if (asset === "SUI") {
|
|
7544
|
+
const result = await selectSuiCoin(tx, ctx.client, ctx.sender, rawAmount, ctx.sponsoredContext);
|
|
7545
|
+
coin = result.coin;
|
|
7546
|
+
effectiveRaw = result.effectiveAmount;
|
|
7547
|
+
} else {
|
|
7548
|
+
const result = await selectAndSplitCoin(tx, ctx.client, ctx.sender, assetInfo.type, rawAmount);
|
|
7549
|
+
coin = result.coin;
|
|
7550
|
+
effectiveRaw = result.effectiveAmount;
|
|
7551
|
+
}
|
|
7552
|
+
addSendToTx(tx, coin, recipient);
|
|
7553
|
+
return {
|
|
7554
|
+
toolName: "send_transfer",
|
|
7555
|
+
effectiveAmount: Number(effectiveRaw) / 10 ** assetInfo.decimals,
|
|
7556
|
+
recipient,
|
|
7557
|
+
asset
|
|
7558
|
+
};
|
|
7559
|
+
},
|
|
7560
|
+
swap_execute: async (tx, input, ctx) => {
|
|
7561
|
+
const fromType = resolveTokenType(input.from);
|
|
7562
|
+
const toType = resolveTokenType(input.to);
|
|
7563
|
+
if (!fromType || !toType) {
|
|
7564
|
+
throw new T2000Error(
|
|
7565
|
+
"ASSET_NOT_SUPPORTED",
|
|
7566
|
+
`Unknown token in swap: from=${input.from}, to=${input.to}`
|
|
7567
|
+
);
|
|
7568
|
+
}
|
|
7569
|
+
const providers = input.providers ?? (ctx.sponsoredContext ? await getSponsoredSwapProviders() : void 0);
|
|
7570
|
+
const result = await addSwapToTx(tx, ctx.client, ctx.sender, {
|
|
7571
|
+
from: input.from,
|
|
7572
|
+
to: input.to,
|
|
7573
|
+
amount: input.amount,
|
|
7574
|
+
slippage: input.slippage,
|
|
7575
|
+
byAmountIn: input.byAmountIn,
|
|
7576
|
+
overlayFee: ctx.overlayFee,
|
|
7577
|
+
providers
|
|
7578
|
+
});
|
|
7579
|
+
tx.transferObjects([result.coin], ctx.sender);
|
|
7580
|
+
return {
|
|
7581
|
+
toolName: "swap_execute",
|
|
7582
|
+
effectiveAmountIn: result.effectiveAmountIn,
|
|
7583
|
+
expectedAmountOut: result.expectedAmountOut,
|
|
7584
|
+
route: result.route
|
|
7585
|
+
};
|
|
7586
|
+
},
|
|
7587
|
+
claim_rewards: async (tx, _input, ctx) => {
|
|
7588
|
+
const rewards = await addClaimRewardsToTx(tx, ctx.client, ctx.sender);
|
|
7589
|
+
return { toolName: "claim_rewards", rewards };
|
|
7590
|
+
},
|
|
7591
|
+
volo_stake: async (tx, input, ctx) => {
|
|
7592
|
+
if (input.amountSui <= 0) {
|
|
7593
|
+
throw new T2000Error("INVALID_AMOUNT", "Stake amount must be greater than zero");
|
|
7594
|
+
}
|
|
7595
|
+
const amountMist = BigInt(Math.floor(input.amountSui * 1e9));
|
|
7596
|
+
const result = await addStakeVSuiToTx(tx, ctx.client, ctx.sender, { amountMist });
|
|
7597
|
+
tx.transferObjects([result.coin], ctx.sender);
|
|
7598
|
+
return { toolName: "volo_stake", effectiveAmountMist: result.effectiveAmountMist };
|
|
7599
|
+
},
|
|
7600
|
+
volo_unstake: async (tx, input, ctx) => {
|
|
7601
|
+
const amountMist = input.amountVSui === "all" ? "all" : BigInt(Math.floor(input.amountVSui * 1e9));
|
|
7602
|
+
if (amountMist !== "all" && amountMist <= 0n) {
|
|
7603
|
+
throw new T2000Error("INVALID_AMOUNT", "Unstake amount must be greater than zero");
|
|
7604
|
+
}
|
|
7605
|
+
const result = await addUnstakeVSuiToTx(tx, ctx.client, ctx.sender, { amountMist });
|
|
7606
|
+
tx.transferObjects([result.coin], ctx.sender);
|
|
7607
|
+
return { toolName: "volo_unstake", effectiveAmountMist: result.effectiveAmountMist };
|
|
7608
|
+
}
|
|
7609
|
+
};
|
|
7610
|
+
function deriveAllowedAddressesFromPtb(tx) {
|
|
7611
|
+
const addresses = /* @__PURE__ */ new Set();
|
|
7612
|
+
const data = tx.getData();
|
|
7613
|
+
for (const cmd of data.commands) {
|
|
7614
|
+
const transferCmd = cmd.TransferObjects;
|
|
7615
|
+
if (!transferCmd) continue;
|
|
7616
|
+
const addressArg = transferCmd.address;
|
|
7617
|
+
if (!addressArg) continue;
|
|
7618
|
+
const addressInputIndex = addressArg.Input;
|
|
7619
|
+
if (addressInputIndex === void 0) continue;
|
|
7620
|
+
const input = data.inputs[addressInputIndex];
|
|
7621
|
+
if (!input) continue;
|
|
7622
|
+
const pureBytes = input.Pure?.bytes;
|
|
7623
|
+
if (!pureBytes) continue;
|
|
7624
|
+
try {
|
|
7625
|
+
const bytes = base64ToBytes(pureBytes);
|
|
7626
|
+
if (bytes.length !== 32) continue;
|
|
7627
|
+
const hex = "0x" + Array.from(bytes).map((b2) => b2.toString(16).padStart(2, "0")).join("");
|
|
7628
|
+
addresses.add(hex);
|
|
7629
|
+
} catch {
|
|
7630
|
+
}
|
|
7631
|
+
}
|
|
7632
|
+
return Array.from(addresses);
|
|
7633
|
+
}
|
|
7634
|
+
function base64ToBytes(b64) {
|
|
7635
|
+
if (typeof Buffer !== "undefined") {
|
|
7636
|
+
return Uint8Array.from(Buffer.from(b64, "base64"));
|
|
7637
|
+
}
|
|
7638
|
+
const binary = atob(b64);
|
|
7639
|
+
const bytes = new Uint8Array(binary.length);
|
|
7640
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
7641
|
+
return bytes;
|
|
7642
|
+
}
|
|
7643
|
+
async function composeTx(opts) {
|
|
7644
|
+
const tx = new Transaction();
|
|
7645
|
+
tx.setSender(opts.sender);
|
|
7646
|
+
const ctx = {
|
|
7647
|
+
client: opts.client,
|
|
7648
|
+
sender: opts.sender,
|
|
7649
|
+
sponsoredContext: opts.sponsoredContext ?? false,
|
|
7650
|
+
overlayFee: opts.overlayFee
|
|
7651
|
+
};
|
|
7652
|
+
const previews = [];
|
|
7653
|
+
for (const step of opts.steps) {
|
|
7654
|
+
const appender = WRITE_APPENDER_REGISTRY[step.toolName];
|
|
7655
|
+
if (!appender) {
|
|
7656
|
+
throw new T2000Error(
|
|
7657
|
+
"UNKNOWN",
|
|
7658
|
+
`No fragment appender registered for tool '${step.toolName}'. Allowed: ${Object.keys(WRITE_APPENDER_REGISTRY).join(", ")}`
|
|
7659
|
+
);
|
|
7660
|
+
}
|
|
7661
|
+
const preview = await appender(tx, step.input, ctx);
|
|
7662
|
+
previews.push(preview);
|
|
7663
|
+
}
|
|
7664
|
+
const txKindBytes = await tx.build({ client: opts.client, onlyTransactionKind: true });
|
|
7665
|
+
const derivedAllowedAddresses = deriveAllowedAddressesFromPtb(tx);
|
|
7666
|
+
return {
|
|
7667
|
+
tx,
|
|
7668
|
+
txKindBytes,
|
|
7669
|
+
derivedAllowedAddresses,
|
|
7670
|
+
perStepPreviews: previews
|
|
7671
|
+
};
|
|
7672
|
+
}
|
|
7673
|
+
|
|
7191
7674
|
// src/protocols/protocolFee.ts
|
|
7192
7675
|
var FEE_RATES = {
|
|
7193
7676
|
save: SAVE_FEE_BPS,
|
|
@@ -7401,6 +7884,6 @@ init_volo();
|
|
|
7401
7884
|
(*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
7402
7885
|
*/
|
|
7403
7886
|
|
|
7404
|
-
export { ALL_NAVI_ASSETS, BORROW_FEE_BPS, BPS_DENOMINATOR, CETUS_USDC_SUI_POOL, CLOCK_ID, COIN_REGISTRY, ContactManager, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, ETH_TYPE, GAS_RESERVE_MIN, HF_CRITICAL_THRESHOLD, HF_WARN_THRESHOLD, IKA_TYPE, KNOWN_TARGETS, KeypairSigner, LABEL_PATTERNS, LOFI_TYPE, MANIFEST_TYPE, MIST_PER_SUI, NAVX_TYPE, NaviAdapter, OPERATION_ASSETS, OUTBOUND_OPS, OVERLAY_FEE_RATE, ProtocolRegistry, SAVE_FEE_BPS, STABLE_ASSETS, SUI_DECIMALS, SUI_TYPE, SUPPORTED_ASSETS, SafeguardEnforcer, SafeguardError, T2000, T2000Error, T2000_OVERLAY_FEE_WALLET, TOKEN_MAP, USDC_DECIMALS, USDC_TYPE, USDE_TYPE, USDSUI_TYPE, USDT_TYPE, VOLO_METADATA, VOLO_PKG, VOLO_POOL, VSUI_TYPE, WAL_TYPE, WBTC_TYPE, ZkLoginSigner, addFeeTransfer, allDescriptors, assertAllowedAsset, buildStakeVSuiTx, buildSwapTx, buildUnstakeVSuiTx, calculateFee, classifyAction, classifyLabel, classifyTransaction, exportPrivateKey, extractTransferDetails, extractTxCommands, extractTxSender, fallbackLabel, findSwapRoute, formatAssetAmount, formatSui, formatUsd, generateKeypair, getAddress, getCoinMeta, getDecimals, getDecimalsForCoinType, getFinancialSummary, getPendingRewards, getRates, getSwapQuote, getTier, getVoloStats, isAllowedAsset, isInRegistry, isSupported, isTier1, isTier2, keypairFromPrivateKey, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, naviDescriptor, normalizeCoinType, parseSuiRpcTx, queryHistory, queryTransaction, rawToStable, rawToUsdc, refineLendingLabel, resolveSymbol, resolveTokenType, saveKey, simulateTransaction, stableToRaw, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
|
|
7887
|
+
export { ALL_NAVI_ASSETS, BORROW_FEE_BPS, BPS_DENOMINATOR, CETUS_USDC_SUI_POOL, CLOCK_ID, COIN_REGISTRY, ContactManager, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, ETH_TYPE, GAS_RESERVE_MIN, HF_CRITICAL_THRESHOLD, HF_WARN_THRESHOLD, IKA_TYPE, KNOWN_TARGETS, KeypairSigner, LABEL_PATTERNS, LOFI_TYPE, MANIFEST_TYPE, MIST_PER_SUI, NAVX_TYPE, NaviAdapter, OPERATION_ASSETS, OUTBOUND_OPS, OVERLAY_FEE_RATE, ProtocolRegistry, SAVE_FEE_BPS, STABLE_ASSETS, SUI_DECIMALS, SUI_TYPE, SUPPORTED_ASSETS, SafeguardEnforcer, SafeguardError, T2000, T2000Error, T2000_OVERLAY_FEE_WALLET, TOKEN_MAP, USDC_DECIMALS, USDC_TYPE, USDE_TYPE, USDSUI_TYPE, USDT_TYPE, VOLO_METADATA, VOLO_PKG, VOLO_POOL, VSUI_TYPE, WAL_TYPE, WBTC_TYPE, WRITE_APPENDER_REGISTRY, ZkLoginSigner, addFeeTransfer, addSendToTx, addStakeVSuiToTx, addSwapToTx, addUnstakeVSuiToTx, allDescriptors, assertAllowedAsset, buildClaimRewardsTx, buildSendTx, buildStakeVSuiTx, buildSwapTx, buildUnstakeVSuiTx, calculateFee, classifyAction, classifyLabel, classifyTransaction, composeTx, deriveAllowedAddressesFromPtb, exportPrivateKey, extractTransferDetails, extractTxCommands, extractTxSender, fallbackLabel, fetchAllCoins, findSwapRoute, formatAssetAmount, formatSui, formatUsd, generateKeypair, getAddress, getCoinMeta, getDecimals, getDecimalsForCoinType, getFinancialSummary, getPendingRewards, getRates, getSwapQuote, getTier, getVoloStats, isAllowedAsset, isInRegistry, isSupported, isTier1, isTier2, keypairFromPrivateKey, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, naviDescriptor, normalizeCoinType, parseSuiRpcTx, queryHistory, queryTransaction, rawToStable, rawToUsdc, refineLendingLabel, resolveSymbol, resolveTokenType, saveKey, selectAndSplitCoin, selectSuiCoin, simulateTransaction, stableToRaw, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
|
|
7405
7888
|
//# sourceMappingURL=index.js.map
|
|
7406
7889
|
//# sourceMappingURL=index.js.map
|