@ninsei-labs/sdk 0.40.0-develop.1 → 0.40.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,3 +1,23 @@
1
+ ## 0.40.0 — 2026-10-11
2
+
3
+ THE ASYNCHRONOUS ROUTE PROVIDERS REACH `latest`. This release moves the tag from 0.39.3; the demo pins this exact
4
+ version rather than the tag.
5
+
6
+ - Four asynchronous route providers, each declaring what it settles: CoWSwap (native), KyberSwap Limit Order
7
+ (wrapped: a liquidity leg, never the sole provider for a native need), UniswapX (native), and the relayed
8
+ Uniswap route through the UniversalRouter (native).
9
+ - `submitUniswapxOrder` publishes an order through a submitter you name; the package never carries an API key.
10
+ - A route can be composed of two legs - liquidity to the wrapped token, then a native leg - and a provider that
11
+ cannot carry the route to what the person needs can never be chosen alone.
12
+ - The engine mirror is regenerated from the source of truth and the vendored browser bundle is rebuilt.
13
+ - The config names the demo's current escrow (factory `0x1029D6bC53f6b9919F8ec6Ac922327F7e5A3DdF2`, cashier
14
+ `0x7E84035B4f42219F3fCE22855c6Dd7D36942B019`, registry `0x416d548B497d3AE808807172a5Bc3549512a64E5`): the
15
+ demo redeployed on 2026-10-11 and the retired router is gone from the configuration.
16
+ - The test wallet adapter signs on the demo network: `arbitrum-sepolia` is on its allowlist, and it no longer
17
+ takes a gas price from a tick behind, which came out below the next block's base fee and was rejected.
18
+
19
+ The synchronous swap path is untouched: nothing that already existed changed behaviour.
20
+
1
21
  ## 0.40.0-develop.1 — 2026-10-10
2
22
 
3
23
  A build of the asynchronous route-provider work, published for the demo and for our own testing. This build does NOT
@@ -363,14 +363,19 @@ export const CHAINS = [
363
363
  explorerName: "arbiscan (sepolia)",
364
364
  gasUsd: 0.01,
365
365
  routeType: "atomic",
366
- // THE DEMO'S MAIN NETWORK: the escrow went here, and the FEE ROUTER IS DEPLOYED here - also the factory (it
367
- // spawns escrows, keeps the rate, holds the fee cashier). The address is a FACT, not an intention:
368
- // 0xaEB1c0455C76551dcEb2E6B1245B65F0458b0aE8 (height 314323871, transaction
369
- // 0x7a88c0249867b76b11c6cb678e6092fdc19404b51540a64c5fd03f5a32f74826, code 8223 bytes, keccak256
370
- // 0x90f26f641b48a2a630463195d4429b0818d29187563e09711a40811fcf08a0ba); it added EARLY REFUND in the dead
371
- // zone - with no mark, refund is open right after readyBy and it publishes the depositor's half. The code
372
- // matches the current repo build byte for byte.
373
- // `npm run check:deployed -- --address=0xaEB1c0455C76551dcEb2E6B1245B65F0458b0aE8`).
366
+ // THE DEMO'S MAIN NETWORK: the Ninsei escrow factory, the interface's fee cashier and the maker registry live
367
+ // here; the ArrakisFeeRouter is gone. The factory is a FACT, not an intention:
368
+ // 0x1029D6bC53f6b9919F8ec6Ac922327F7e5A3DdF2 (height 318033203, transaction
369
+ // 0x0f82c556f056f2dcaba5c12da75a749c257dfb1ccbf0eb6962a4e7f0119d166d, code 4226 bytes, keccak256
370
+ // 0x4b515f600c641bffde054b3a98f4e26bd43d2dd2b2d8e60e8cfe36ee03686dd9); every order is an EIP-1167 clone and
371
+ // the factory carries the pair (implementation(), implementationCodeHash()). The fee cashier is the second CREATE
372
+ // of the same pass - 0x7E84035B4f42219F3fCE22855c6Dd7D36942B019 (height 318033206, code 573 bytes, keccak256
373
+ // 0xcca1d8bc53d1d1c98901570800e093d0933f84637c6cdc727153b3ef8d8c3c36); the maker registry is the third -
374
+ // 0x416d548B497d3AE808807172a5Bc3549512a64E5 (height 318033209, code 4557 bytes). The code matches the current
375
+ // repo build byte for byte.
376
+ // `npm run check:deployed -- --address=0x1029D6bC53f6b9919F8ec6Ac922327F7e5A3DdF2`).
377
+ // PREVIOUS (the ArrakisFeeRouter of the previous rules, now removed): 0xaEB1c0455C76551dcEb2E6B1245B65F0458b0aE8
378
+ // (height 314323871, code 8223 bytes, keccak256 0x90f26f641b48a2a630463195d4429b0818d29187563e09711a40811fcf08a0ba).
374
379
  // PREVIOUS (ceiling 3%, no early refund): 0xEa619bDC78989627093B7830990367B2ECE52CE5 (height 314309038,
375
380
  // code 8143 bytes). PREVIOUS live (router with a 10% ceiling): 0x9f856cd9c14fd9493961473b804039b09a4012ef
376
381
  // (height 313597131, code 8723 bytes). PREVIOUS before it (factory without a fee):
@@ -379,9 +384,9 @@ export const CHAINS = [
379
384
  // (createOrderAndFund; the escrow has no separate funding function - an order is born funded, see FACTORY_METHODS
380
385
  // in www/js/evm/factory.js and ESCROW_METHODS in escrow.js). The old lock(sealedHalf) and hashlock are gone: the
381
386
  // half is not sent but revealed by presentation. Switching back to "simulated" is one edit, to show a demo with
382
- // no money movement. cashier: the INTERFACE's fee cashier, named in quotes. The contracts on chain are still the
383
- // previous ones, so there is no cashier there: the field is filled in the same pass as the factory address.
384
- escrow: { address: "0xaEB1c0455C76551dcEb2E6B1245B65F0458b0aE8", mode: "live", cashier: null },
387
+ // no money movement. cashier: the INTERFACE's fee cashier, named in quotes and now deployed (the second CREATE of
388
+ // the same pass). implementationCodeHash: the escrow implementation the factory carries, checked against the chain.
389
+ escrow: { address: "0x1029D6bC53f6b9919F8ec6Ac922327F7e5A3DdF2", mode: "live", cashier: "0x7E84035B4f42219F3fCE22855c6Dd7D36942B019", implementationCodeHash: "0xfd1ef12c1d96d3ee7060bd5901e06108723783403fad00c9630dcdeb6193674b" },
385
390
  tokens: [
386
391
  // Test USDC (Circle): decimals 6 and symbol "USDC" verified on chain by the same node.
387
392
  { symbol: "USDC", address: "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d", decimals: 6, usd: 1, cls: "ar-token-usdc" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ninsei-labs/sdk",
3
- "version": "0.40.0-develop.1",
3
+ "version": "0.40.0",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org/"
@@ -43,8 +43,11 @@ export const CLAIMER_ENV = "NINSEI_TEST_EVM_CLAIMER";
43
43
  // the registry's production networks the escrow is marked "simulated", that is, by the letter of the rule they are
44
44
  // not production. So the test key would also sign on mainnet - the engine would not notice, and the engine's rule
45
45
  // must not be changed (it is shared by the page and all legs). So the "signing is ALLOWED here" marker is set
46
- // separately and EXPLICITLY: only what is listed, and nothing more. First - the local anvil by chainId 31337.
47
- export const TEST_CHAIN_IDS = Object.freeze([31337]);
46
+ // separately and EXPLICITLY: only what is listed, and nothing more. The local anvil by chainId 31337, and the
47
+ // demo testnet arbitrum-sepolia by chainId 421614 - the network the demo escrow lives on (the registry entry
48
+ // marks it testnet: true with a live escrow, so the second line below already passes; without it in THIS list
49
+ // the first line refuses the whole demo contour, and no headless run can sign).
50
+ export const TEST_CHAIN_IDS = Object.freeze([31337, 421614]);
48
51
 
49
52
  const envOf = (name) => {
50
53
  const box = typeof process !== "undefined" && process ? process.env : null;
@@ -302,7 +305,16 @@ export function nodeTestEvmWallet({ privateKey, rpcUrl, chainId = null, id = "no
302
305
  const remote = await assertTestContour();
303
306
  const valueWei = BigInt(value === undefined || value === null ? 0 : value);
304
307
  const nonce = Number(BigInt(await provider.request({ method: "eth_getTransactionCount", params: [owner, "pending"] })));
305
- const gasPrice = BigInt(await provider.request({ method: "eth_gasPrice" }));
308
+ // NEVER SIGN BELOW THE BLOCK BASE FEE. On a live node eth_gasPrice answers a tick behind and comes out
309
+ // slightly BELOW the next block's base - the signature is then rejected with "max fee per gas less than
310
+ // block base fee". The node's own sender already carries this rule (rfq/evm.mjs: base + base/8); the test
311
+ // adapter must not diverge from it, or a headless run cannot send anything on such a network.
312
+ let gasPrice = BigInt(await provider.request({ method: "eth_gasPrice" }));
313
+ try {
314
+ const block = await provider.request({ method: "eth_getBlockByNumber", params: ["latest", false] });
315
+ const baseFee = block && block.baseFeePerGas ? BigInt(block.baseFeePerGas) : 0n;
316
+ if (baseFee > 0n && gasPrice <= baseFee) gasPrice = baseFee + baseFee / 8n;
317
+ } catch { /* the base fee was not read - the node's own price stays */ }
306
318
  let gasLimit = gas === null || gas === undefined ? null : BigInt(gas);
307
319
  if (gasLimit === null) {
308
320
  const est = BigInt(await provider.request({