@anywalletkit/protocol-swap2-thorchain 0.3.5 → 0.4.1
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/README.md +84 -0
- package/dist/{chunk-LYJOENYE.js → chunk-EIAXGWNG.js} +521 -106
- package/dist/chunk-EIAXGWNG.js.map +1 -0
- package/dist/{chunk-QLDZS2KO.js → chunk-YKA6IYKX.js} +2 -2
- package/dist/index.cjs +520 -105
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -2
- package/dist/protocol.cjs +448 -79
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.js +2 -2
- package/dist/provider.cjs +520 -105
- package/dist/provider.cjs.map +1 -1
- package/dist/provider.d.cts +59 -2
- package/dist/provider.d.ts +59 -2
- package/dist/provider.js +3 -1
- package/package.json +6 -6
- package/dist/chunk-LYJOENYE.js.map +0 -1
- /package/dist/{chunk-QLDZS2KO.js.map → chunk-YKA6IYKX.js.map} +0 -0
package/README.md
CHANGED
|
@@ -28,12 +28,96 @@ nodes of different operators (Liquify's gateway and the IBS team's node, both ch
|
|
|
28
28
|
operator; a local mock needs a second mock there). Node URLs must be `https:` (`allowInsecureNodeUrl` for local
|
|
29
29
|
development).
|
|
30
30
|
|
|
31
|
+
### How a second node confirms the vault
|
|
32
|
+
|
|
33
|
+
THORChain keeps several asgard vaults active and its inbound address moves among them every few minutes, so a node a
|
|
34
|
+
few blocks behind the quoting node often still names the previous one. A confirming node agrees when the quoted
|
|
35
|
+
vault is:
|
|
36
|
+
|
|
37
|
+
- its current inbound address for the source chain (`/thorchain/inbound_addresses`), or
|
|
38
|
+
- that chain's address of a vault it lists with status `ActiveVault` (`/thorchain/vaults/asgard`, chain matched
|
|
39
|
+
exactly; EVM addresses compare case-insensitively, others exactly) that its mimir (`/thorchain/mimir`) does not
|
|
40
|
+
flag `CompromisedVault-<pubkey>` or `SolvencyHaltVault-<pubkey>-<chain>`. THORNode leaves such vaults out of inbound
|
|
41
|
+
election and does not credit an inbound to a compromised vault.
|
|
42
|
+
|
|
43
|
+
A `RetiringVault` (or any other status) never confirms. The rest stays as strict: on EVM the router in the node's
|
|
44
|
+
`inbound_addresses` must be the quote's; a halt or trading pause on the source or the destination chain refuses; the
|
|
45
|
+
calldata must still pay exactly the quoted vault.
|
|
46
|
+
|
|
47
|
+
A confirming node is skipped for the next one when it trails the quoting node's THORChain height
|
|
48
|
+
(`/thorchain/lastblock`, the `thorchain` field) by more than `confirmMaxLagBlocks` (default 50 ≈ 5 minutes), does not
|
|
49
|
+
answer within `confirmTimeoutMs` (default 2500 ms), redirects (also when the runtime followed the redirect itself, as
|
|
50
|
+
React Native's fetch does: `res.url` must be the URL asked), or answers in another shape. When every node trails, the
|
|
51
|
+
refusal says so ("no confirming node is within 50 blocks …"); when none answers, it is "no second node answered to
|
|
52
|
+
confirm the inbound vault".
|
|
53
|
+
|
|
54
|
+
**Another shape** includes a field of another type. The type of every field read is checked (THORNode's own types):
|
|
55
|
+
in `inbound_addresses` each entry is an object with a string `chain`, `address`, `router` and `dust_threshold` are
|
|
56
|
+
strings and `halted`, `global_trading_paused` and `chain_trading_paused` booleans when present; in `vaults/asgard`
|
|
57
|
+
`status` is a string, `pub_key` a `thorpub1…` string, `addresses` a list of objects with string `chain` and `address`;
|
|
58
|
+
every `mimir` value is a number or a string (int64), and a vault flag an int64; `lastblock`'s `thorchain` is a
|
|
59
|
+
non-negative int64. One such field anywhere in an answer (another chain's entry or another vault included) skips
|
|
60
|
+
the confirming node, and `verifyBuild` skips it the same way. The quoting node's `inbound_addresses` and `lastblock`
|
|
61
|
+
are read the same way: another shape makes that node unavailable and the next `nodeUrl` host is asked, with the
|
|
62
|
+
existing refusals when none is left ("inbound addresses unavailable from every node", "THORChain height
|
|
63
|
+
(/thorchain/lastblock) unavailable from every node that answered the inbound addresses"; before broadcast "cannot
|
|
64
|
+
refresh inbound addresses before broadcast").
|
|
65
|
+
|
|
66
|
+
**Time.** The vault check has its own 8 s budget. It starts when the quoting node's quote is in hand (before
|
|
67
|
+
broadcast: when a node is asked to refresh the inbound snapshot) and covers that node's `inbound_addresses` and
|
|
68
|
+
`lastblock` reads and every confirming node, each getting `confirmTimeoutMs` or what is left; time a failed host took
|
|
69
|
+
before does not count, and no confirming node is asked with less than 100 ms left. When the budget runs out before
|
|
70
|
+
any confirming node was asked, the refusal is "the 8 s confirmation budget ran out before a second node could be asked to confirm the
|
|
71
|
+
inbound vault — retry". `confirmTimeoutMs` bounds confirming nodes only: each read of the quoting node (the quote,
|
|
72
|
+
`inbound_addresses`, `lastblock`) gets 8 s whatever it is. When a node answers `inbound_addresses` but not
|
|
73
|
+
`lastblock`, the refusal names it: "THORChain height (/thorchain/lastblock) unavailable from every node that answered
|
|
74
|
+
the inbound addresses" (before broadcast: "cannot read THORChain height (/thorchain/lastblock) before broadcast from
|
|
75
|
+
any node that answered the inbound addresses"). Worst case without a caller signal: each `nodeUrl` host takes at most
|
|
76
|
+
8 s for the quote (16 s when a quote without a slippage is retried with a wider tolerance) plus 8 s for its snapshot,
|
|
77
|
+
and the host that quotes is confirmed within the 8 s that started when its quote was in hand: hosts × 16 s, or hosts ×
|
|
78
|
+
24 s with the retry (32 s / 48 s with the two default hosts); `preflightDeposit` hosts × 8 s. A caller's AbortSignal
|
|
79
|
+
(the router passes one: 8 s per provider, 25 s when it is the only one) replaces the 8 s bound of the quote request;
|
|
80
|
+
when it aborts, the quote request, the quoting node's `lastblock` read and the confirming reads stop at once, and its
|
|
81
|
+
`inbound_addresses` read keeps its own 8 s.
|
|
82
|
+
|
|
83
|
+
**Requests a confirming node gets** (`THORNODE_CONFIRM_PATHS`), all `GET`, no query string, no body, headers
|
|
84
|
+
`accept` and `x-client-id` only. A proxy in front of a confirming node can pass exactly these four and refuse
|
|
85
|
+
anything else:
|
|
86
|
+
|
|
87
|
+
| Path | When |
|
|
88
|
+
| --- | --- |
|
|
89
|
+
| `/thorchain/lastblock` | every confirmation |
|
|
90
|
+
| `/thorchain/inbound_addresses` | every confirmation |
|
|
91
|
+
| `/thorchain/vaults/asgard` | when the node's current inbound is not the quoted vault |
|
|
92
|
+
| `/thorchain/mimir` | when the node's current inbound is not the quoted vault |
|
|
93
|
+
|
|
94
|
+
The quoting node (`nodeUrl`) gets `/thorchain/quote/swap?from_asset=…&to_asset=…&amount=…&destination=…` with
|
|
95
|
+
`tolerance_bps` or `liquidity_tolerance_bps`, `streaming_quantity=1` and, when set, `refund_address`, `affiliate`,
|
|
96
|
+
`affiliate_bps`; then `/thorchain/inbound_addresses` and `GET /thorchain/lastblock` (no query string, so a proxy in
|
|
97
|
+
front of a `nodeUrl` must pass it too); `trackIntent` reads `/thorchain/tx/status/<HASH>` and `/thorchain/tx/<HASH>`.
|
|
98
|
+
The quote's `inbound_addresses` read and the quote itself ask for `cache: "no-store"`, which React Native's fetch
|
|
99
|
+
sends as an extra `?_=<time>` query; `lastblock` and the confirming reads set no cache option.
|
|
100
|
+
|
|
31
101
|
Behind `remoteProvider`, the app checks the backend's build itself: `remoteProvider({name: "thorchain", baseUrl,
|
|
32
102
|
...thorchainPins()})` pins the routers and runs `verifyBuild` on the client — the vault in the router call confirmed
|
|
33
103
|
by two nodes, the source asset and exact input, and the memo's destination, refund and limit against the app's own
|
|
34
104
|
request (pass the backend's `affiliate` / `affiliateBps`). The pins open the stub to the Tron deposit route
|
|
35
105
|
(`depositAddressRoutes`): its vault is the one `verifyBuild` confirms.
|
|
36
106
|
|
|
107
|
+
`verifyBuild` confirms the vault by the same rule as the provider's confirming nodes, so an inbound rotation between
|
|
108
|
+
the backend's quote and the device's check does not refuse: current inbound or a non-flagged `ActiveVault` (never
|
|
109
|
+
`RetiringVault` or another status), both chains open, on EVM the node's router equal to the call's. It asks every
|
|
110
|
+
`nodeUrl` node (default: the two public nodes) in parallel on the four `THORNODE_CONFIRM_PATHS` (the same GETs, so the
|
|
111
|
+
same proxy rules), each within `confirmTimeoutMs` (default 2500 ms, so the check takes at most that); a node that
|
|
112
|
+
fails, redirects, answers another shape (a field of another type included, as above), is slower, or trails the
|
|
113
|
+
highest THORChain height the nodes report by more than `confirmMaxLagBlocks` (default 50) is skipped. In `nodeUrl`
|
|
114
|
+
order a node's refusal refuses and two confirming nodes pass. Refusals: "a THORNode reports another inbound vault
|
|
115
|
+
than `<vault>`", "a THORNode reports another router",
|
|
116
|
+
"`<CHAIN>` is halted / paused" (now also the destination chain), "a THORNode lists the inbound vault as `<Status>`, not
|
|
117
|
+
ActiveVault", "a THORNode's mimir flags the inbound vault as compromised" (or `insolvent`), "two THORNodes within 50
|
|
118
|
+
blocks of the highest THORChain height they report could not confirm the inbound vault (behind or unreachable)", "two
|
|
119
|
+
THORNodes could not confirm the inbound vault".
|
|
120
|
+
|
|
37
121
|
## Activity
|
|
38
122
|
|
|
39
123
|
Routers and Asgard vaults rotate, so `describeActivity(tx, ctx)` matches no
|