@forevermoney/sdk 0.1.0 → 0.4.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/CHANGELOG.md +64 -0
- package/README.md +113 -5
- package/dist/index.cjs +646 -245
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +87 -32
- package/dist/index.d.ts +87 -32
- package/dist/index.js +655 -231
- package/dist/index.js.map +1 -1
- package/examples/viem.ts +64 -0
- package/package.json +8 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,69 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0 — 2026-09-16
|
|
4
|
+
|
|
5
|
+
- Added `asset: 'sn80'` to the bridge builders and preparation methods for Base
|
|
6
|
+
SN80 ↔ Finney subnet-80 stake. Existing calls continue to default to TAO.
|
|
7
|
+
- Added the verified Base and Finney SN80 token addresses and `SN80_NETUID`.
|
|
8
|
+
- SN80 staking approvals use netuid 80 and alpha RAO; ERC-20 approvals use the
|
|
9
|
+
Base SN80 token. The partner fee remains 0% and the full principal crosses.
|
|
10
|
+
- Rejects unsupported SN80 liquid TAO conversion, other subnets, and other
|
|
11
|
+
EVM lanes before requesting a quote.
|
|
12
|
+
- Added an optional `partnerFee: { recipient, bps }` to every bridge builder and
|
|
13
|
+
`prepare*` method. The fee is charged on top of the bridged amount via the V5
|
|
14
|
+
`*WithFee` entrypoints and paid to the recipient on the source chain; the full
|
|
15
|
+
amount still crosses. `prepare*` enforces the gateway's `maxIntegratorFeeBps`.
|
|
16
|
+
Added `partnerFeeWei` to `BridgePreparation`, `MAX_PARTNER_FEE_BPS`,
|
|
17
|
+
`partnerFeeCut`, `partnerFeeTaoTopUp`, and the `INVALID_PARTNER_FEE` error
|
|
18
|
+
code. Omitting the fee keeps the zero-fee calls and byte-identical plans.
|
|
19
|
+
The hub quote uses the deployed `quoteBridgeOutWithFee(…, taoAmount,
|
|
20
|
+
stakedAlphaRao, fee)` signature and cross-checks its top-ups against the SDK.
|
|
21
|
+
- SN80 plans keep `minTaoOut` equal to the bridged amount, like TAO.
|
|
22
|
+
- Updated deployment metadata version to 1.2.0.
|
|
23
|
+
|
|
24
|
+
## 0.3.0 — 2026-09-16
|
|
25
|
+
|
|
26
|
+
- Moved bridging to the V5 gateways. `contracts.gateway` is now
|
|
27
|
+
`0x1da2415229b614C787e145D1D7346eb496319C52` on Base,
|
|
28
|
+
`0xf27fdA637131E25B2A1b4865ED9597d881980c7E` on Robinhood, and
|
|
29
|
+
`0xcd0C6d98D0A126B1c113d15b4c28F38321437787` on Subtensor. Existing approvals
|
|
30
|
+
for the old gateways do not carry over.
|
|
31
|
+
- Added `contracts.legacyGateway` with the previous gateway addresses. Receipt
|
|
32
|
+
parsing and CCIP delivery tracking accept both, so bridges sent through the old
|
|
33
|
+
gateways can still be tracked.
|
|
34
|
+
- Added the V5 `*WithFee` bridge entrypoints, `maxIntegratorFeeBps`,
|
|
35
|
+
`bridgeFeeBps`, `integratorTaoTopUp`, and the `NotDelivered` event to the ABIs.
|
|
36
|
+
Plans still use the zero-fee entrypoints; the partner fee is 0%.
|
|
37
|
+
- Fixed the `claimableToken` ABI argument names to `(token, account)`, the
|
|
38
|
+
order the gateway has always used. The selector is unchanged.
|
|
39
|
+
- `getCcipDeliveryStatus` reports `recovery` when the Subtensor gateway emits
|
|
40
|
+
`NotDelivered`, not only `Claimable`.
|
|
41
|
+
- Added `MIN_LIQUID_SUBTENSOR_TO_EVM_WEI`: bridging liquid TAO from Subtensor
|
|
42
|
+
requires at least 0.002 TAO.
|
|
43
|
+
- Plan regression fixtures now check the V5 plans, which differ from the
|
|
44
|
+
originals only in the gateway address.
|
|
45
|
+
|
|
46
|
+
## 0.2.0 — 2026-09-10
|
|
47
|
+
|
|
48
|
+
- Replaced ethers with viem 2.56.3 for RPC clients, ABI encoding, gas estimation,
|
|
49
|
+
event decoding, and transaction tracking.
|
|
50
|
+
- Replaced `@polkadot/util` and `@polkadot/util-crypto` with PAPI's
|
|
51
|
+
`@polkadot-api/substrate-bindings` 0.21.1 for SS58 validation and mirror addresses.
|
|
52
|
+
- Added `toViemTransaction()` and a typed example that reuses existing viem clients.
|
|
53
|
+
Retained the dependency-free `toEthersTransaction()` compatibility adapter.
|
|
54
|
+
- Lower-level tracking functions accept viem public clients and retain support
|
|
55
|
+
for ethers-style JSON-RPC providers through a dependency-free adapter. The
|
|
56
|
+
high-level transport interface, human-readable ABIs, and plan format are unchanged.
|
|
57
|
+
- Enforced the plan's canonical chain in `toViemTransaction()` and rejected
|
|
58
|
+
unsupported chain IDs before signing.
|
|
59
|
+
- Preserved uppercase EVM address normalization and mixed-case checksum validation.
|
|
60
|
+
- Added regression tests for wrong-chain signing, legacy provider tracking, and
|
|
61
|
+
address normalization.
|
|
62
|
+
- Added original-implementation plan and address regression fixtures; migrated
|
|
63
|
+
offline tests, fork tests, and the guarded live canary to the new libraries.
|
|
64
|
+
- Fixed the Base canary to request staked delivery: its 0.001 TAO maximum is below
|
|
65
|
+
the 0.01 TAO liquid-delivery minimum. Broadcast guards and funding caps remain.
|
|
66
|
+
|
|
3
67
|
## 0.1.0
|
|
4
68
|
|
|
5
69
|
- Added canonical Base and Subtensor production deployment metadata.
|
package/README.md
CHANGED
|
@@ -11,6 +11,11 @@ is transferred 1:1 and the network fee is charged separately, so the SDK fixes
|
|
|
11
11
|
the contract's minimum destination output to the bridged principal instead of
|
|
12
12
|
exposing configurable slippage.
|
|
13
13
|
|
|
14
|
+
Bridge plans use the V5 gateways in `contracts.gateway`. The previous gateways
|
|
15
|
+
remain under `contracts.legacyGateway` only so receipts and deliveries of
|
|
16
|
+
bridges sent through them can still be tracked. Plans call the zero-fee V5
|
|
17
|
+
entrypoints unless a `partnerFee` is passed (see "Charge a partner fee").
|
|
18
|
+
|
|
14
19
|
## Install
|
|
15
20
|
|
|
16
21
|
```bash
|
|
@@ -19,6 +24,12 @@ npm install @forevermoney/sdk
|
|
|
19
24
|
|
|
20
25
|
Node.js 22 or newer is required. Both ESM and CommonJS builds are published.
|
|
21
26
|
|
|
27
|
+
The SDK uses viem for EVM reads, ABI encoding, and receipt decoding, and
|
|
28
|
+
PAPI's `@polkadot-api/substrate-bindings` for SS58 and EVM mirror addresses.
|
|
29
|
+
It does not require ethers or the legacy `@polkadot/*` packages. The full PAPI
|
|
30
|
+
RPC client is unnecessary because the bridge executes on Subtensor EVM;
|
|
31
|
+
this SDK does not sign native Substrate extrinsics.
|
|
32
|
+
|
|
22
33
|
## Create a client
|
|
23
34
|
|
|
24
35
|
```ts
|
|
@@ -54,8 +65,10 @@ const foreverMoney = createForeverMoneyClient({
|
|
|
54
65
|
})
|
|
55
66
|
```
|
|
56
67
|
|
|
57
|
-
|
|
58
|
-
|
|
68
|
+
Existing viem public clients can supply their `.transport` directly. See
|
|
69
|
+
[`examples/viem.ts`](./examples/viem.ts) for transport reuse and execution with a
|
|
70
|
+
viem wallet client, or [`examples/talisman.ts`](./examples/talisman.ts) for
|
|
71
|
+
raw EIP-1193 account and transaction handling.
|
|
59
72
|
|
|
60
73
|
## Prepare a bridge
|
|
61
74
|
|
|
@@ -105,11 +118,92 @@ method.
|
|
|
105
118
|
|
|
106
119
|
For a staked source, pass the stake `netuid`. The SDK reads the staking
|
|
107
120
|
precompile allowance and expresses the approval in RAO.
|
|
121
|
+
For a liquid Subtensor source, the SDK requires at least 0.002 TAO because the
|
|
122
|
+
gateway stakes it before bridging. This minimum does not apply to an existing
|
|
123
|
+
staked source.
|
|
108
124
|
|
|
109
125
|
The bridge does not deduct its fee from the destination amount. For both
|
|
110
126
|
directions, the SDK encodes the bridge amount itself as the contract's minimum
|
|
111
127
|
output; callers cannot weaken that invariant.
|
|
112
128
|
|
|
129
|
+
## Bridge SN80 on Base
|
|
130
|
+
|
|
131
|
+
Pass `asset: 'sn80'` to bridge Base SN80 to a Finney subnet-80 staked position,
|
|
132
|
+
or bridge existing subnet-80 stake back to Base SN80. The default asset is `tao`,
|
|
133
|
+
so existing TAO integrations keep their behavior. SN80 is supported on the Base
|
|
134
|
+
lane with staked input/delivery; liquid TAO conversion and the Robinhood SN80
|
|
135
|
+
lane are not supported by these methods.
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
const toFinney = await foreverMoney.bridge.prepareBaseToSubtensor({
|
|
139
|
+
asset: 'sn80',
|
|
140
|
+
sender: '0x...',
|
|
141
|
+
amountWei: 100n * 10n ** 18n, // 100 SN80
|
|
142
|
+
destination: '5...',
|
|
143
|
+
delivery: 'staked',
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
const toBase = await foreverMoney.bridge.prepareSubtensorToBase({
|
|
147
|
+
asset: 'sn80',
|
|
148
|
+
sender: '0x...',
|
|
149
|
+
recipient: '0x...',
|
|
150
|
+
amountWei: 100n * 10n ** 18n, // 100 staked SN80
|
|
151
|
+
source: 'staked',
|
|
152
|
+
})
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
SN80 uses 18-decimal token units, restricted to whole alpha RAO (multiples of
|
|
156
|
+
`10^9` token wei). The Finney approval uses the staking precompile and netuid
|
|
157
|
+
`80` automatically; an explicitly different `netuid` is rejected. Base approves
|
|
158
|
+
the SN80 ERC-20 to the V5 gateway. Both directions bridge the full SN80 amount
|
|
159
|
+
with a 0% partner fee and charge network fees separately. The liquid TAO
|
|
160
|
+
minimums do not apply to SN80 stake. SN80 delivery is always staked
|
|
161
|
+
(`wantLiquid: false`), so the gateway never converts the stake into TAO.
|
|
162
|
+
|
|
163
|
+
Bridging staked SN80 from Finney pulls the caller's alpha from the vault's own
|
|
164
|
+
validator hotkey on netuid 80 (`AlphaVault.positionOf(SN80)`). Stake held with
|
|
165
|
+
any other SN80 validator cannot be bridged until it is moved to that hotkey.
|
|
166
|
+
|
|
167
|
+
Canonical SN80 token addresses are exported as `contracts.wrappedSn80`:
|
|
168
|
+
|
|
169
|
+
- Base: `0x6F63d869011f95274498023b4ABFC00b30c34378`
|
|
170
|
+
- Finney: `0xfD628dE75EF96f0A5C59659159C6cA81E0DC2222`
|
|
171
|
+
|
|
172
|
+
The Base address `0x2292233d308188fcb3775f63a20f31dff6db02d9` is the SN80/TAO
|
|
173
|
+
liquidity pool; bridge calls use the token addresses above.
|
|
174
|
+
|
|
175
|
+
## Charge a partner fee
|
|
176
|
+
|
|
177
|
+
Integrators can take a fee on each bridge by passing `partnerFee` to any bridge
|
|
178
|
+
builder or preparation method. The fee is charged **on top** of `amountWei` and
|
|
179
|
+
paid to `recipient` on the source chain in the same transaction; the full
|
|
180
|
+
`amountWei` always crosses, and `minTaoOut` / `minTokenOut` still bound it.
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
const prepared = await foreverMoney.bridge.prepareBaseToSubtensor({
|
|
184
|
+
sender: '0x...',
|
|
185
|
+
amountWei: 100n * 10n ** 18n,
|
|
186
|
+
destination: '5...',
|
|
187
|
+
delivery: 'staked',
|
|
188
|
+
partnerFee: { recipient: '0xYourTreasury', bps: 100 }, // 1%
|
|
189
|
+
})
|
|
190
|
+
prepared.partnerFeeWei // 1 TAO: what the sender pays on top
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
What the sender supplies extra, per direction:
|
|
194
|
+
|
|
195
|
+
| Direction | Extra input | Plan effect |
|
|
196
|
+
| ---------------------------- | ------------------------------------------------- | ------------------------------------------------------- |
|
|
197
|
+
| Base / Robinhood → Subtensor | `amount × bps / 10 000` of the token | approval covers `amount + cut`; `bridgeToFinneyWithFee` |
|
|
198
|
+
| Subtensor → EVM, liquid | `partnerFeeTaoTopUp(amount, bps)` TAO (whole RAO) | added to the transaction value; `bridgeOutWithFee` |
|
|
199
|
+
| Subtensor → EVM, staked | `alphaRao × bps / 10 000` of the caller's alpha | staking approval covers it; `bridgeOutWithFee` |
|
|
200
|
+
|
|
201
|
+
`bps` must be an integer from 0 to 10 000; `0` or omitting `partnerFee` uses the
|
|
202
|
+
original zero-fee entrypoints, so existing plans are unchanged. Each gateway caps
|
|
203
|
+
the fee at `maxIntegratorFeeBps` (1% at deployment, governance can raise it to
|
|
204
|
+
10%); `prepare*` reads the cap and throws `INVALID_PARTNER_FEE` when `bps`
|
|
205
|
+
exceeds it. The recipient must not be the zero address or the gateway.
|
|
206
|
+
|
|
113
207
|
## Track bridge delivery
|
|
114
208
|
|
|
115
209
|
Capture the destination block immediately before broadcasting the source bridge
|
|
@@ -163,9 +257,23 @@ for (const step of prepared.plan.steps) {
|
|
|
163
257
|
}
|
|
164
258
|
```
|
|
165
259
|
|
|
166
|
-
|
|
167
|
-
`
|
|
168
|
-
|
|
260
|
+
Viem consumers can pass `toViemTransaction(step.transaction)` to
|
|
261
|
+
`walletClient.sendTransaction()`. The adapter supplies the canonical `chain`
|
|
262
|
+
for the plan, so viem rejects a wallet connected to another network. Do not
|
|
263
|
+
override that chain or disable viem's chain assertion. The adapter maps
|
|
264
|
+
`from` to `account`, `gasLimit` to `gas`, and decimal quantities to `bigint`.
|
|
265
|
+
Confirm the signing account and chain before every signature. Local-account
|
|
266
|
+
signers must pass their account object explicitly, after checking that its
|
|
267
|
+
address matches the plan's sender.
|
|
268
|
+
|
|
269
|
+
`toEthersTransaction()` remains as a dependency-free compatibility adapter for
|
|
270
|
+
existing consumers. All adapters validate decimal quantities before conversion.
|
|
271
|
+
The exported lower-level tracking functions accept either a viem `PublicClient`
|
|
272
|
+
or an existing ethers-style provider with `send(method, params)`. Legacy
|
|
273
|
+
providers are adapted through their own transport without an ethers dependency.
|
|
274
|
+
The `createForeverMoneyClient()` transport interface is unchanged. Exported
|
|
275
|
+
`foreverMoneyAbis` remain human-readable; use viem's `parseAbi()` when calling
|
|
276
|
+
contracts directly.
|
|
169
277
|
|
|
170
278
|
If a plan contains an approval, its later transaction intentionally has no gas
|
|
171
279
|
limit: that transaction cannot be simulated against pre-approval state. The
|