@forevermoney/sdk 0.5.2 → 0.5.3
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/CHANGELOG.md +14 -0
- package/README.md +9 -4
- package/dist/index.cjs +35 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +35 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.3 — 2026-09-19
|
|
4
|
+
|
|
5
|
+
- Increased EVM-to-Subtensor CCIP destination execution gas from the spoke
|
|
6
|
+
gateways' 300,000 default to an explicit 3,500,000. A 900,000 manual
|
|
7
|
+
execution reached the gateway but still fell back to a claimable booking;
|
|
8
|
+
the same live liquid claim path estimates near 2,560,000 gas. Quotes and
|
|
9
|
+
transaction calldata now use the same exported
|
|
10
|
+
`EVM_TO_SUBTENSOR_DESTINATION_GAS_LIMIT` for zero-fee and partner-fee
|
|
11
|
+
bridges. Callers can override it per transaction with the optional
|
|
12
|
+
`destinationGasLimit` request field, without changing or republishing the
|
|
13
|
+
SDK.
|
|
14
|
+
- Added the explicit-gas `quoteBridgeToFinney` and `bridgeToFinney` overloads
|
|
15
|
+
to the public SpokeGateway ABI.
|
|
16
|
+
|
|
3
17
|
## 0.5.2 — 2026-09-16
|
|
4
18
|
|
|
5
19
|
- Added opt-in stake rounding adjustment to Subtensor bridge preparation, with an explicit disable option and adjusted amount/plan metadata. Searches only on `StrandedStake`, preserves minimum output, requotes candidates and checks source balances, minimum remainders and partner-fee allocations. Approval-required plans are explicitly marked as not yet simulated.
|
package/README.md
CHANGED
|
@@ -6,10 +6,10 @@ vault contracts.
|
|
|
6
6
|
The SDK owns the canonical production deployment: chain IDs, CCIP selectors,
|
|
7
7
|
contract addresses, ABIs, and protocol-specific amount conversion. An
|
|
8
8
|
integrator supplies only RPC transports and user input. The SDK never accepts a
|
|
9
|
-
private key, signs a transaction, or broadcasts a transaction.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
private key, signs a transaction, or broadcasts a transaction. Network fees are
|
|
10
|
+
charged separately. Subtensor-to-EVM requests accept an explicit minimum output
|
|
11
|
+
to account for native staking rounding; exact output remains the default.
|
|
12
|
+
SDK 0.5.2 also provides opt-in stake rounding preparation (see below).
|
|
13
13
|
|
|
14
14
|
Bridge plans use the current gateways in `contracts.gateway`. Retired gateways
|
|
15
15
|
remain under `contracts.legacyGateways` only so receipts and deliveries of
|
|
@@ -101,6 +101,11 @@ Liquid Base-to-Subtensor delivery requires at least `0.01 TAO` because the
|
|
|
101
101
|
destination vault must unstake the bridged position. The SDK rejects smaller
|
|
102
102
|
liquid deliveries with `AMOUNT_BELOW_MINIMUM` before quoting or planning them;
|
|
103
103
|
staked delivery does not use this liquid-unstaking minimum.
|
|
104
|
+
EVM-to-Subtensor plans quote and encode an explicit 3,500,000 destination gas
|
|
105
|
+
limit so the variable-cost Subtensor exit path can auto-execute through CCIP.
|
|
106
|
+
The policy is exported as `EVM_TO_SUBTENSOR_DESTINATION_GAS_LIMIT`. Pass a
|
|
107
|
+
positive bigint as `destinationGasLimit` to override it for one preparation or
|
|
108
|
+
plan; the SDK uses that value for both the fee quote and transaction calldata.
|
|
104
109
|
The network-fee buffer is 2% and the estimated-gas buffer is 50%; both policies
|
|
105
110
|
are exported as bigint basis-point constants and covered by property tests.
|
|
106
111
|
|
package/dist/index.cjs
CHANGED
|
@@ -23,6 +23,7 @@ __export(index_exports, {
|
|
|
23
23
|
BASE_CCIP_SELECTOR: () => BASE_CCIP_SELECTOR,
|
|
24
24
|
BASE_CHAIN_ID: () => BASE_CHAIN_ID,
|
|
25
25
|
BASIS_POINTS: () => BASIS_POINTS,
|
|
26
|
+
EVM_TO_SUBTENSOR_DESTINATION_GAS_LIMIT: () => EVM_TO_SUBTENSOR_DESTINATION_GAS_LIMIT,
|
|
26
27
|
EVM_WEI_PER_RAO: () => EVM_WEI_PER_RAO,
|
|
27
28
|
FOREVERMONEY_DEPLOYMENT_VERSION: () => FOREVERMONEY_DEPLOYMENT_VERSION,
|
|
28
29
|
ForeverMoneyError: () => ForeverMoneyError,
|
|
@@ -645,7 +646,9 @@ var SPOKE_GATEWAY_ABI = Object.freeze([
|
|
|
645
646
|
"function maxIntegratorFeeBps() view returns (uint16)",
|
|
646
647
|
"function bridgeFeeBps() view returns (uint16)",
|
|
647
648
|
"function quoteBridgeToFinney(address token,uint256 amount,(bytes32 ss58,address evmFallback,bool wantLiquid,uint256 minTaoOut) exit) view returns (uint256 fee)",
|
|
649
|
+
"function quoteBridgeToFinney(address token,uint256 amount,(bytes32 ss58,address evmFallback,bool wantLiquid,uint256 minTaoOut) exit,uint256 gasLimit) view returns (uint256 fee)",
|
|
648
650
|
"function bridgeToFinney(address token,uint256 amount,(bytes32 ss58,address evmFallback,bool wantLiquid,uint256 minTaoOut) exit) payable returns (bytes32 messageId)",
|
|
651
|
+
"function bridgeToFinney(address token,uint256 amount,(bytes32 ss58,address evmFallback,bool wantLiquid,uint256 minTaoOut) exit,uint256 gasLimit) payable returns (bytes32 messageId)",
|
|
649
652
|
"function quoteBridgeToFinneyWithFee(address token,uint256 amount,(bytes32 ss58,address evmFallback,bool wantLiquid,uint256 minTaoOut) exit,uint256 gasLimit,(address recipient,uint16 bps) integrator) view returns (uint256 fee,uint256 cut,uint256 amountCrossing)",
|
|
650
653
|
"function bridgeToFinneyWithFee(address token,uint256 amount,(bytes32 ss58,address evmFallback,bool wantLiquid,uint256 minTaoOut) exit,uint256 gasLimit,(address recipient,uint16 bps) integrator) payable returns (bytes32 messageId)",
|
|
651
654
|
"event BridgedToFinney(address indexed token,address indexed sender,bytes32 indexed ss58,uint256 amount,bytes32 messageId)"
|
|
@@ -663,7 +666,6 @@ var ALPHA_GATEWAY_ABI = Object.freeze([
|
|
|
663
666
|
"function bridgeOutWithFee(uint64 destSelector,address token,address recipient,uint256 taoAmount,uint256 stakedAlphaRao,uint256 minTokenOut,(address recipient,uint16 bps) integrator) payable returns (bytes32 messageId)",
|
|
664
667
|
"function bridgeOutFromValidators(uint64 destSelector,address token,address recipient,uint256 taoAmount,(bytes32 validator,uint256 alphaRao)[] sources,uint256 minTokenOut) payable returns (bytes32 messageId)",
|
|
665
668
|
"function bridgeOutFromValidatorsWithFee(uint64 destSelector,address token,address recipient,uint256 taoAmount,(bytes32 validator,uint256 alphaRao)[] sources,uint256 minTokenOut,(address recipient,uint16 bps) integrator) payable returns (bytes32 messageId)",
|
|
666
|
-
"function minStakeRequired() view returns (uint256)",
|
|
667
669
|
"function MAX_STAKE_SOURCES() view returns (uint256)",
|
|
668
670
|
"function GATEWAY_COLDKEY() view returns (bytes32)",
|
|
669
671
|
"function claimLiquid(address token,uint256 minTaoOut,address to)",
|
|
@@ -750,6 +752,18 @@ var stakingAbi = (0, import_viem6.parseAbi)(STAKING_ABI);
|
|
|
750
752
|
var MIN_LIQUID_EVM_TO_SUBTENSOR_WEI = 10000000000000000n;
|
|
751
753
|
var MIN_LIQUID_BASE_TO_SUBTENSOR_WEI = MIN_LIQUID_EVM_TO_SUBTENSOR_WEI;
|
|
752
754
|
var MIN_LIQUID_SUBTENSOR_TO_EVM_WEI = 2000000n * EVM_WEI_PER_RAO;
|
|
755
|
+
var EVM_TO_SUBTENSOR_DESTINATION_GAS_LIMIT = 3500000n;
|
|
756
|
+
function resolveDestinationGasLimit(value) {
|
|
757
|
+
const gasLimit = value ?? EVM_TO_SUBTENSOR_DESTINATION_GAS_LIMIT;
|
|
758
|
+
if (typeof gasLimit !== "bigint" || gasLimit <= 0n) {
|
|
759
|
+
throw new ForeverMoneyError(
|
|
760
|
+
"INVALID_TRANSACTION_PLAN",
|
|
761
|
+
"Destination gas limit must be a positive bigint.",
|
|
762
|
+
{ destinationGasLimit: String(gasLimit) }
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
return gasLimit;
|
|
766
|
+
}
|
|
753
767
|
var MAX_PARTNER_FEE_BPS = 1e4;
|
|
754
768
|
var MAX_STAKE_PULLS = 16;
|
|
755
769
|
var NO_PARTNER_FEE = {
|
|
@@ -926,15 +940,15 @@ function partnerFeeSummary(charged, unit, fee) {
|
|
|
926
940
|
if (fee.bps === 0) return "";
|
|
927
941
|
return ` Partner fee: ${charged} wei of ${unit} (${fee.bps} bps) on top, paid to ${fee.recipient}.`;
|
|
928
942
|
}
|
|
929
|
-
function encodeSpokeBridge(token, amountWei, exit, fee) {
|
|
943
|
+
function encodeSpokeBridge(token, amountWei, exit, destinationGasLimit, fee) {
|
|
930
944
|
return fee.bps === 0 ? (0, import_viem6.encodeFunctionData)({
|
|
931
945
|
abi: spokeAbi,
|
|
932
946
|
functionName: "bridgeToFinney",
|
|
933
|
-
args: [token, amountWei, exit]
|
|
947
|
+
args: [token, amountWei, exit, destinationGasLimit]
|
|
934
948
|
}) : (0, import_viem6.encodeFunctionData)({
|
|
935
949
|
abi: spokeAbi,
|
|
936
950
|
functionName: "bridgeToFinneyWithFee",
|
|
937
|
-
args: [token, amountWei, exit,
|
|
951
|
+
args: [token, amountWei, exit, destinationGasLimit, fee]
|
|
938
952
|
});
|
|
939
953
|
}
|
|
940
954
|
function resolveStakePulls(pulls, amountRao) {
|
|
@@ -1021,7 +1035,7 @@ function encodeHubBridge(destSelector, token, recipient, taoAmount, stakedAlphaR
|
|
|
1021
1035
|
args: [...args, fee]
|
|
1022
1036
|
});
|
|
1023
1037
|
}
|
|
1024
|
-
async function quoteSpokeWithFee(provider, gateway, token, amountWei, exit, fee) {
|
|
1038
|
+
async function quoteSpokeWithFee(provider, gateway, token, amountWei, exit, destinationGasLimit, fee) {
|
|
1025
1039
|
const maxBps = await provider.readContract({
|
|
1026
1040
|
address: gateway,
|
|
1027
1041
|
abi: spokeAbi,
|
|
@@ -1032,7 +1046,7 @@ async function quoteSpokeWithFee(provider, gateway, token, amountWei, exit, fee)
|
|
|
1032
1046
|
address: gateway,
|
|
1033
1047
|
abi: spokeAbi,
|
|
1034
1048
|
functionName: "quoteBridgeToFinneyWithFee",
|
|
1035
|
-
args: [token, amountWei, exit,
|
|
1049
|
+
args: [token, amountWei, exit, destinationGasLimit, fee]
|
|
1036
1050
|
});
|
|
1037
1051
|
return networkFee;
|
|
1038
1052
|
}
|
|
@@ -1078,6 +1092,9 @@ function buildEvmToSubtensorPlan(input) {
|
|
|
1078
1092
|
assertBaseToSubtensorAmount(input.amountWei, input.delivery);
|
|
1079
1093
|
assertNonNegativeAmount(input.allowanceWei, "Token allowance");
|
|
1080
1094
|
assertNonNegativeAmount(input.exactNetworkFeeWei, "Network fee");
|
|
1095
|
+
const destinationGasLimit = resolveDestinationGasLimit(
|
|
1096
|
+
input.destinationGasLimit
|
|
1097
|
+
);
|
|
1081
1098
|
const destination = normalizeSS58(input.destination);
|
|
1082
1099
|
const exit = {
|
|
1083
1100
|
ss58: ss58ToPublicKey(destination),
|
|
@@ -1121,6 +1138,7 @@ function buildEvmToSubtensorPlan(input) {
|
|
|
1121
1138
|
asset.evmToken,
|
|
1122
1139
|
input.amountWei,
|
|
1123
1140
|
exit,
|
|
1141
|
+
destinationGasLimit,
|
|
1124
1142
|
partnerFee
|
|
1125
1143
|
),
|
|
1126
1144
|
value,
|
|
@@ -1236,6 +1254,9 @@ async function prepareEvmToSubtensor(provider, input) {
|
|
|
1236
1254
|
assertDelivery(input.delivery);
|
|
1237
1255
|
assertAssetMode(input.asset, input.delivery);
|
|
1238
1256
|
assertBaseToSubtensorAmount(input.amountWei, input.delivery);
|
|
1257
|
+
const destinationGasLimit = resolveDestinationGasLimit(
|
|
1258
|
+
input.destinationGasLimit
|
|
1259
|
+
);
|
|
1239
1260
|
const destination = normalizeSS58(input.destination);
|
|
1240
1261
|
const evm = getForeverMoneyEvmDeployment(input.evmChain);
|
|
1241
1262
|
const exit = {
|
|
@@ -1260,13 +1281,19 @@ async function prepareEvmToSubtensor(provider, input) {
|
|
|
1260
1281
|
address: evm.contracts.gateway,
|
|
1261
1282
|
abi: spokeAbi,
|
|
1262
1283
|
functionName: "quoteBridgeToFinney",
|
|
1263
|
-
args: [
|
|
1284
|
+
args: [
|
|
1285
|
+
asset.evmToken,
|
|
1286
|
+
input.amountWei,
|
|
1287
|
+
exit,
|
|
1288
|
+
destinationGasLimit
|
|
1289
|
+
]
|
|
1264
1290
|
}) : quoteSpokeWithFee(
|
|
1265
1291
|
provider,
|
|
1266
1292
|
evm.contracts.gateway,
|
|
1267
1293
|
asset.evmToken,
|
|
1268
1294
|
input.amountWei,
|
|
1269
1295
|
exit,
|
|
1296
|
+
destinationGasLimit,
|
|
1270
1297
|
partnerFee
|
|
1271
1298
|
)
|
|
1272
1299
|
]);
|
|
@@ -1276,6 +1303,7 @@ async function prepareEvmToSubtensor(provider, input) {
|
|
|
1276
1303
|
asset.evmToken,
|
|
1277
1304
|
input.amountWei,
|
|
1278
1305
|
exit,
|
|
1306
|
+
destinationGasLimit,
|
|
1279
1307
|
partnerFee
|
|
1280
1308
|
);
|
|
1281
1309
|
estimatedBridgeGas = await provider.estimateGas({
|