@forevermoney/sdk 0.2.0 → 0.5.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 CHANGED
@@ -1,5 +1,66 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0 — 2026-09-16
4
+
5
+ - Staked bridges from Subtensor can pull from several validators. Pass
6
+ `stakePulls: [{ hotkey, amountRao }]` (1–16 entries, unique hotkeys, summing
7
+ to the bridged amount) and the plan calls the V5.1 gateway's
8
+ `bridgeOutFromValidators` (or `…WithFee`), which re-delegates every pull to
9
+ the token's canonical validator before depositing. Without `stakePulls` the
10
+ plan keeps the single-validator `bridgeOut` call. With a partner fee the cut
11
+ is charged on top and spread across the pulls in proportion to their
12
+ amounts, so each position needs headroom for its share. Added `StakePull`, `MAX_STAKE_PULLS`, and the
13
+ `bridgeOutFromValidators*`, `minStakeRequired`, `MAX_STAKE_SOURCES` and
14
+ `GATEWAY_COLDKEY` ABI entries.
15
+ - Moved the Subtensor gateway to the V5.1 deployment at
16
+ `0xd5Fa238aa4177f6c1341491969d9cBeec94EEd69`. `contracts.legacyGateway` is
17
+ now `contracts.legacyGateways`, a list of retired hubs (oldest first) used for
18
+ receipt and delivery tracking; the V5 hub stays listed because the spoke
19
+ gateways still deliver through it. Deployment metadata version is 1.3.0.
20
+
21
+ ## 0.4.0 — 2026-09-16
22
+
23
+ - Added `asset: 'sn80'` to the bridge builders and preparation methods for Base
24
+ SN80 ↔ Finney subnet-80 stake. Existing calls continue to default to TAO.
25
+ - Added the verified Base and Finney SN80 token addresses and `SN80_NETUID`.
26
+ - SN80 staking approvals use netuid 80 and alpha RAO; ERC-20 approvals use the
27
+ Base SN80 token. The partner fee remains 0% and the full principal crosses.
28
+ - Rejects unsupported SN80 liquid TAO conversion, other subnets, and other
29
+ EVM lanes before requesting a quote.
30
+ - Added an optional `partnerFee: { recipient, bps }` to every bridge builder and
31
+ `prepare*` method. The fee is charged on top of the bridged amount via the V5
32
+ `*WithFee` entrypoints and paid to the recipient on the source chain; the full
33
+ amount still crosses. `prepare*` enforces the gateway's `maxIntegratorFeeBps`.
34
+ Added `partnerFeeWei` to `BridgePreparation`, `MAX_PARTNER_FEE_BPS`,
35
+ `partnerFeeCut`, `partnerFeeTaoTopUp`, and the `INVALID_PARTNER_FEE` error
36
+ code. Omitting the fee keeps the zero-fee calls and byte-identical plans.
37
+ The hub quote uses the deployed `quoteBridgeOutWithFee(…, taoAmount,
38
+ stakedAlphaRao, fee)` signature and cross-checks its top-ups against the SDK.
39
+ - SN80 plans keep `minTaoOut` equal to the bridged amount, like TAO.
40
+ - Updated deployment metadata version to 1.2.0.
41
+
42
+ ## 0.3.0 — 2026-09-16
43
+
44
+ - Moved bridging to the V5 gateways. `contracts.gateway` is now
45
+ `0x1da2415229b614C787e145D1D7346eb496319C52` on Base,
46
+ `0xf27fdA637131E25B2A1b4865ED9597d881980c7E` on Robinhood, and
47
+ `0xcd0C6d98D0A126B1c113d15b4c28F38321437787` on Subtensor. Existing approvals
48
+ for the old gateways do not carry over.
49
+ - Added `contracts.legacyGateway` with the previous gateway addresses. Receipt
50
+ parsing and CCIP delivery tracking accept both, so bridges sent through the old
51
+ gateways can still be tracked.
52
+ - Added the V5 `*WithFee` bridge entrypoints, `maxIntegratorFeeBps`,
53
+ `bridgeFeeBps`, `integratorTaoTopUp`, and the `NotDelivered` event to the ABIs.
54
+ Plans still use the zero-fee entrypoints; the partner fee is 0%.
55
+ - Fixed the `claimableToken` ABI argument names to `(token, account)`, the
56
+ order the gateway has always used. The selector is unchanged.
57
+ - `getCcipDeliveryStatus` reports `recovery` when the Subtensor gateway emits
58
+ `NotDelivered`, not only `Claimable`.
59
+ - Added `MIN_LIQUID_SUBTENSOR_TO_EVM_WEI`: bridging liquid TAO from Subtensor
60
+ requires at least 0.002 TAO.
61
+ - Plan regression fixtures now check the V5 plans, which differ from the
62
+ originals only in the gateway address.
63
+
3
64
  ## 0.2.0 — 2026-09-10
4
65
 
5
66
  - Replaced ethers with viem 2.56.3 for RPC clients, ABI encoding, gas estimation,
package/README.md CHANGED
@@ -11,6 +11,14 @@ 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 current gateways in `contracts.gateway`. Retired gateways
15
+ remain under `contracts.legacyGateways` only so receipts and deliveries of
16
+ bridges sent through them can still be tracked. A spoke gateway's Subtensor
17
+ hub pointer is immutable, so after a hub-only redeploy EVM-to-Subtensor
18
+ deliveries still arrive through the previous hub; the SDK watches every known
19
+ hub, so tracking and recovery detection are unaffected. Plans call the zero-fee V5
20
+ entrypoints unless a `partnerFee` is passed (see "Charge a partner fee").
21
+
14
22
  ## Install
15
23
 
16
24
  ```bash
@@ -113,11 +121,122 @@ method.
113
121
 
114
122
  For a staked source, pass the stake `netuid`. The SDK reads the staking
115
123
  precompile allowance and expresses the approval in RAO.
124
+ For a liquid Subtensor source, the SDK requires at least 0.002 TAO because the
125
+ gateway stakes it before bridging. This minimum does not apply to an existing
126
+ staked source.
116
127
 
117
128
  The bridge does not deduct its fee from the destination amount. For both
118
129
  directions, the SDK encodes the bridge amount itself as the contract's minimum
119
130
  output; callers cannot weaken that invariant.
120
131
 
132
+ ## Bridge SN80 on Base
133
+
134
+ Pass `asset: 'sn80'` to bridge Base SN80 to a Finney subnet-80 staked position,
135
+ or bridge existing subnet-80 stake back to Base SN80. The default asset is `tao`,
136
+ so existing TAO integrations keep their behavior. SN80 is supported on the Base
137
+ lane with staked input/delivery; liquid TAO conversion and the Robinhood SN80
138
+ lane are not supported by these methods.
139
+
140
+ ```ts
141
+ const toFinney = await foreverMoney.bridge.prepareBaseToSubtensor({
142
+ asset: 'sn80',
143
+ sender: '0x...',
144
+ amountWei: 100n * 10n ** 18n, // 100 SN80
145
+ destination: '5...',
146
+ delivery: 'staked',
147
+ })
148
+
149
+ const toBase = await foreverMoney.bridge.prepareSubtensorToBase({
150
+ asset: 'sn80',
151
+ sender: '0x...',
152
+ recipient: '0x...',
153
+ amountWei: 100n * 10n ** 18n, // 100 staked SN80
154
+ source: 'staked',
155
+ })
156
+ ```
157
+
158
+ SN80 uses 18-decimal token units, restricted to whole alpha RAO (multiples of
159
+ `10^9` token wei). The Finney approval uses the staking precompile and netuid
160
+ `80` automatically; an explicitly different `netuid` is rejected. Base approves
161
+ the SN80 ERC-20 to the V5 gateway. Both directions bridge the full SN80 amount
162
+ with a 0% partner fee and charge network fees separately. The liquid TAO
163
+ minimums do not apply to SN80 stake. SN80 delivery is always staked
164
+ (`wantLiquid: false`), so the gateway never converts the stake into TAO.
165
+
166
+ Bridging staked SN80 from Finney pulls the caller's alpha from the vault's own
167
+ validator hotkey on netuid 80 (`AlphaVault.positionOf(SN80)`). Stake held with
168
+ any other SN80 validator cannot be bridged until it is moved to that hotkey.
169
+
170
+ Canonical SN80 token addresses are exported as `contracts.wrappedSn80`:
171
+
172
+ - Base: `0x6F63d869011f95274498023b4ABFC00b30c34378`
173
+ - Finney: `0xfD628dE75EF96f0A5C59659159C6cA81E0DC2222`
174
+
175
+ The Base address `0x2292233d308188fcb3775f63a20f31dff6db02d9` is the SN80/TAO
176
+ liquidity pool; bridge calls use the token addresses above.
177
+
178
+ ## Bridge stake held with several validators
179
+
180
+ Staked alpha on Finney is keyed by validator hotkey, and a bridge can only pull
181
+ from the positions you name. Pass `stakePulls` to draw from more than one
182
+ validator; the gateway re-delegates each pull to the token's canonical
183
+ validator and deposits the total, so stake with any validator can be bridged.
184
+
185
+ ```ts
186
+ const prepared = await foreverMoney.bridge.prepareSubtensorToBase({
187
+ sender: '0x...',
188
+ recipient: '0x...',
189
+ amountWei: 140n * 10n ** 18n,
190
+ source: 'staked',
191
+ netuid: 0n,
192
+ stakePulls: [
193
+ { hotkey: '0x…validatorA', amountRao: 100_000_000_000n },
194
+ { hotkey: '0x…validatorB', amountRao: 40_000_000_000n },
195
+ ],
196
+ })
197
+ ```
198
+
199
+ Rules the SDK checks before building a plan: 1 to `MAX_STAKE_PULLS` (16)
200
+ entries, unique non-zero hotkeys, positive amounts, and a sum equal to the
201
+ bridged amount in RAO. One staking approval on the netuid covers every pull.
202
+ Nothing on-chain enforces the runtime's minimum stake on what you leave behind
203
+ (`minStakeRequired()`, 0.02 TAO-equivalent), so size each pull to either drain
204
+ the position or leave at least that much. With a partner fee the cut is charged
205
+ on top and spread across the pulls in proportion to their amounts, so each
206
+ position needs headroom for its share.
207
+
208
+ ## Charge a partner fee
209
+
210
+ Integrators can take a fee on each bridge by passing `partnerFee` to any bridge
211
+ builder or preparation method. The fee is charged **on top** of `amountWei` and
212
+ paid to `recipient` on the source chain in the same transaction; the full
213
+ `amountWei` always crosses, and `minTaoOut` / `minTokenOut` still bound it.
214
+
215
+ ```ts
216
+ const prepared = await foreverMoney.bridge.prepareBaseToSubtensor({
217
+ sender: '0x...',
218
+ amountWei: 100n * 10n ** 18n,
219
+ destination: '5...',
220
+ delivery: 'staked',
221
+ partnerFee: { recipient: '0xYourTreasury', bps: 100 }, // 1%
222
+ })
223
+ prepared.partnerFeeWei // 1 TAO: what the sender pays on top
224
+ ```
225
+
226
+ What the sender supplies extra, per direction:
227
+
228
+ | Direction | Extra input | Plan effect |
229
+ | ---------------------------- | ------------------------------------------------- | ------------------------------------------------------- |
230
+ | Base / Robinhood → Subtensor | `amount × bps / 10 000` of the token | approval covers `amount + cut`; `bridgeToFinneyWithFee` |
231
+ | Subtensor → EVM, liquid | `partnerFeeTaoTopUp(amount, bps)` TAO (whole RAO) | added to the transaction value; `bridgeOutWithFee` |
232
+ | Subtensor → EVM, staked | `alphaRao × bps / 10 000` of the caller's alpha | staking approval covers it; `bridgeOutWithFee` |
233
+
234
+ `bps` must be an integer from 0 to 10 000; `0` or omitting `partnerFee` uses the
235
+ original zero-fee entrypoints, so existing plans are unchanged. Each gateway caps
236
+ the fee at `maxIntegratorFeeBps` (1% at deployment, governance can raise it to
237
+ 10%); `prepare*` reads the cap and throws `INVALID_PARTNER_FEE` when `bps`
238
+ exceeds it. The recipient must not be the zero address or the gateway.
239
+
121
240
  ## Track bridge delivery
122
241
 
123
242
  Capture the destination block immediately before broadcasting the source bridge