@vultisig/rujira 1.0.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.
Files changed (118) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +254 -0
  3. package/dist/assets/amount.d.ts +80 -0
  4. package/dist/assets/amount.d.ts.map +1 -0
  5. package/dist/assets/amount.js +186 -0
  6. package/dist/assets/asset.d.ts +43 -0
  7. package/dist/assets/asset.d.ts.map +1 -0
  8. package/dist/assets/asset.js +1 -0
  9. package/dist/assets/formats.d.ts +54 -0
  10. package/dist/assets/formats.d.ts.map +1 -0
  11. package/dist/assets/formats.js +164 -0
  12. package/dist/assets/index.d.ts +27 -0
  13. package/dist/assets/index.d.ts.map +1 -0
  14. package/dist/assets/index.js +45 -0
  15. package/dist/assets/registry.d.ts +37 -0
  16. package/dist/assets/registry.d.ts.map +1 -0
  17. package/dist/assets/registry.js +487 -0
  18. package/dist/assets/router.d.ts +44 -0
  19. package/dist/assets/router.d.ts.map +1 -0
  20. package/dist/assets/router.js +142 -0
  21. package/dist/client.d.ts +70 -0
  22. package/dist/client.d.ts.map +1 -0
  23. package/dist/client.js +250 -0
  24. package/dist/config/constants.d.ts +25 -0
  25. package/dist/config/constants.d.ts.map +1 -0
  26. package/dist/config/constants.js +36 -0
  27. package/dist/config.d.ts +41 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +72 -0
  30. package/dist/discovery/discovery.d.ts +39 -0
  31. package/dist/discovery/discovery.d.ts.map +1 -0
  32. package/dist/discovery/discovery.js +250 -0
  33. package/dist/discovery/graphql-client.d.ts +46 -0
  34. package/dist/discovery/graphql-client.d.ts.map +1 -0
  35. package/dist/discovery/graphql-client.js +137 -0
  36. package/dist/discovery/index.d.ts +9 -0
  37. package/dist/discovery/index.d.ts.map +1 -0
  38. package/dist/discovery/index.js +7 -0
  39. package/dist/discovery/types.d.ts +62 -0
  40. package/dist/discovery/types.d.ts.map +1 -0
  41. package/dist/discovery/types.js +5 -0
  42. package/dist/easy-routes.d.ts +216 -0
  43. package/dist/easy-routes.d.ts.map +1 -0
  44. package/dist/easy-routes.js +241 -0
  45. package/dist/errors.d.ts +65 -0
  46. package/dist/errors.d.ts.map +1 -0
  47. package/dist/errors.js +184 -0
  48. package/dist/index.d.ts +46 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +46 -0
  51. package/dist/modules/assets.d.ts +68 -0
  52. package/dist/modules/assets.d.ts.map +1 -0
  53. package/dist/modules/assets.js +127 -0
  54. package/dist/modules/deposit.d.ts +152 -0
  55. package/dist/modules/deposit.d.ts.map +1 -0
  56. package/dist/modules/deposit.js +233 -0
  57. package/dist/modules/index.d.ts +12 -0
  58. package/dist/modules/index.d.ts.map +1 -0
  59. package/dist/modules/index.js +9 -0
  60. package/dist/modules/orderbook.d.ts +80 -0
  61. package/dist/modules/orderbook.d.ts.map +1 -0
  62. package/dist/modules/orderbook.js +320 -0
  63. package/dist/modules/swap.d.ts +48 -0
  64. package/dist/modules/swap.d.ts.map +1 -0
  65. package/dist/modules/swap.js +318 -0
  66. package/dist/modules/withdraw.d.ts +46 -0
  67. package/dist/modules/withdraw.d.ts.map +1 -0
  68. package/dist/modules/withdraw.js +218 -0
  69. package/dist/services/fee-estimator.d.ts +14 -0
  70. package/dist/services/fee-estimator.d.ts.map +1 -0
  71. package/dist/services/fee-estimator.js +89 -0
  72. package/dist/services/price-impact.d.ts +11 -0
  73. package/dist/services/price-impact.d.ts.map +1 -0
  74. package/dist/services/price-impact.js +58 -0
  75. package/dist/signer/index.d.ts +3 -0
  76. package/dist/signer/index.d.ts.map +1 -0
  77. package/dist/signer/index.js +1 -0
  78. package/dist/signer/keysign-builder.d.ts +21 -0
  79. package/dist/signer/keysign-builder.d.ts.map +1 -0
  80. package/dist/signer/keysign-builder.js +106 -0
  81. package/dist/signer/types.d.ts +81 -0
  82. package/dist/signer/types.d.ts.map +1 -0
  83. package/dist/signer/types.js +8 -0
  84. package/dist/signer/vultisig-provider.d.ts +33 -0
  85. package/dist/signer/vultisig-provider.d.ts.map +1 -0
  86. package/dist/signer/vultisig-provider.js +242 -0
  87. package/dist/types.d.ts +375 -0
  88. package/dist/types.d.ts.map +1 -0
  89. package/dist/types.js +18 -0
  90. package/dist/utils/cache.d.ts +87 -0
  91. package/dist/utils/cache.d.ts.map +1 -0
  92. package/dist/utils/cache.js +124 -0
  93. package/dist/utils/denom-conversion.d.ts +47 -0
  94. package/dist/utils/denom-conversion.d.ts.map +1 -0
  95. package/dist/utils/denom-conversion.js +105 -0
  96. package/dist/utils/encoding.d.ts +17 -0
  97. package/dist/utils/encoding.d.ts.map +1 -0
  98. package/dist/utils/encoding.js +55 -0
  99. package/dist/utils/format.d.ts +108 -0
  100. package/dist/utils/format.d.ts.map +1 -0
  101. package/dist/utils/format.js +213 -0
  102. package/dist/utils/index.d.ts +10 -0
  103. package/dist/utils/index.d.ts.map +1 -0
  104. package/dist/utils/index.js +9 -0
  105. package/dist/utils/memo.d.ts +107 -0
  106. package/dist/utils/memo.d.ts.map +1 -0
  107. package/dist/utils/memo.js +190 -0
  108. package/dist/utils/rate-limiter.d.ts +38 -0
  109. package/dist/utils/rate-limiter.d.ts.map +1 -0
  110. package/dist/utils/rate-limiter.js +67 -0
  111. package/dist/utils/type-guards.d.ts +22 -0
  112. package/dist/utils/type-guards.d.ts.map +1 -0
  113. package/dist/utils/type-guards.js +27 -0
  114. package/dist/validation/address-validator.d.ts +15 -0
  115. package/dist/validation/address-validator.d.ts.map +1 -0
  116. package/dist/validation/address-validator.js +75 -0
  117. package/package.json +98 -0
  118. package/src/__tests__/live/README.md +47 -0
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Type guard to check if an object is a valid Asset with a secured FIN denom.
3
+ * Secured assets follow the `chain-symbol` pattern (e.g., `btc-btc`, `eth-usdc-0xa0b8...`).
4
+ * Native tokens (`rune`, `tcy`) and module tokens (`x/ruji`) are excluded.
5
+ * @internal
6
+ */
7
+ export function isFinAsset(obj) {
8
+ if (!obj || typeof obj !== 'object')
9
+ return false;
10
+ const asset = obj;
11
+ return (typeof asset.formats === 'object' &&
12
+ asset.formats !== null &&
13
+ typeof asset.formats.fin === 'string' &&
14
+ asset.formats.fin.includes('-'));
15
+ }
16
+ /**
17
+ * Parse a THORChain asset string into chain and symbol components.
18
+ * @param asset - Asset string (e.g., "BTC.BTC", "ETH.USDC-0xA0b8...")
19
+ * @internal
20
+ */
21
+ export function parseAsset(asset) {
22
+ const parts = asset.split('.');
23
+ return {
24
+ chain: parts[0]?.toUpperCase() || '',
25
+ symbol: parts.slice(1).join('.') || '',
26
+ };
27
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Address validation for L1 chains and THORChain
3
+ * @module validation/address-validator
4
+ */
5
+ /**
6
+ * Validate an L1 chain address.
7
+ * Throws RujiraError if the address is invalid.
8
+ */
9
+ export declare function validateL1Address(chain: string, address: string): void;
10
+ /**
11
+ * Validate a THORChain bech32 address (thor1...).
12
+ * Throws RujiraError if the address is invalid.
13
+ */
14
+ export declare function validateThorAddress(address: string): void;
15
+ //# sourceMappingURL=address-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address-validator.d.ts","sourceRoot":"","sources":["../../src/validation/address-validator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6BH;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAmBtE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAwCzD"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Address validation for L1 chains and THORChain
3
+ * @module validation/address-validator
4
+ */
5
+ import { fromBech32 } from '@cosmjs/encoding';
6
+ import { RujiraError, RujiraErrorCode } from '../errors.js';
7
+ const evmValidator = (addr) => /^0x[a-fA-F0-9]{40}$/.test(addr);
8
+ const L1_ADDRESS_VALIDATORS = {
9
+ BTC: addr => /^(1|3)[a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(addr) || /^bc1[a-z0-9]{39,87}$/.test(addr),
10
+ ETH: evmValidator,
11
+ BSC: evmValidator,
12
+ AVAX: evmValidator,
13
+ BASE: evmValidator,
14
+ ARB: evmValidator,
15
+ GAIA: addr => /^cosmos1[a-z0-9]{38}$/.test(addr),
16
+ NOBLE: addr => /^noble1[a-z0-9]{38}$/.test(addr),
17
+ DOGE: addr => /^D[a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(addr),
18
+ DASH: addr => /^[X7][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(addr),
19
+ LTC: addr => /^[LM3][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(addr) || /^ltc1[a-z0-9]{39,87}$/.test(addr),
20
+ BCH: addr => /^(1|3)[a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(addr) ||
21
+ /^bitcoincash:[qp][a-z0-9]{41}$/.test(addr) ||
22
+ /^[qp][a-z0-9]{41}$/.test(addr),
23
+ XRP: addr => /^r[1-9A-HJ-NP-Za-km-z]{24,34}$/.test(addr),
24
+ TRON: addr => /^T[a-zA-Z0-9]{33}$/.test(addr),
25
+ ZEC: addr => /^t1[a-km-zA-HJ-NP-Z1-9]{33}$/.test(addr) || /^t3[a-km-zA-HJ-NP-Z1-9]{33}$/.test(addr),
26
+ };
27
+ /**
28
+ * Validate an L1 chain address.
29
+ * Throws RujiraError if the address is invalid.
30
+ */
31
+ export function validateL1Address(chain, address) {
32
+ if (!address || address.trim().length === 0) {
33
+ throw new RujiraError(RujiraErrorCode.INVALID_ADDRESS, `${chain} address is required`);
34
+ }
35
+ const validator = L1_ADDRESS_VALIDATORS[chain.toUpperCase()];
36
+ if (validator) {
37
+ if (!validator(address)) {
38
+ throw new RujiraError(RujiraErrorCode.INVALID_ADDRESS, `Invalid ${chain} address: ${address}`);
39
+ }
40
+ }
41
+ else {
42
+ // Fallback: non-empty, reasonable length
43
+ if (address.length < 10 || address.length > 128) {
44
+ throw new RujiraError(RujiraErrorCode.INVALID_ADDRESS, `Invalid ${chain} address: expected 10-128 characters, got ${address.length}`);
45
+ }
46
+ }
47
+ }
48
+ /**
49
+ * Validate a THORChain bech32 address (thor1...).
50
+ * Throws RujiraError if the address is invalid.
51
+ */
52
+ export function validateThorAddress(address) {
53
+ if (!address || typeof address !== 'string') {
54
+ throw new RujiraError(RujiraErrorCode.INVALID_ADDRESS, 'Destination address is required');
55
+ }
56
+ const trimmed = address.trim();
57
+ if (!trimmed.startsWith('thor1')) {
58
+ throw new RujiraError(RujiraErrorCode.INVALID_ADDRESS, `Invalid destination address format: must start with 'thor1'. Got: ${address.substring(0, 10)}...`);
59
+ }
60
+ try {
61
+ const decoded = fromBech32(trimmed);
62
+ if (decoded.prefix !== 'thor') {
63
+ throw new RujiraError(RujiraErrorCode.INVALID_ADDRESS, `Invalid address prefix: expected 'thor', got '${decoded.prefix}'`);
64
+ }
65
+ if (decoded.data.length !== 20 && decoded.data.length !== 32) {
66
+ throw new RujiraError(RujiraErrorCode.INVALID_ADDRESS, `Invalid address data length: expected 20 or 32 bytes, got ${decoded.data.length}`);
67
+ }
68
+ }
69
+ catch (error) {
70
+ if (error instanceof RujiraError) {
71
+ throw error;
72
+ }
73
+ throw new RujiraError(RujiraErrorCode.INVALID_ADDRESS, `Invalid bech32 address: ${error instanceof Error ? error.message : 'checksum verification failed'}`);
74
+ }
75
+ }
package/package.json ADDED
@@ -0,0 +1,98 @@
1
+ {
2
+ "name": "@vultisig/rujira",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "Rujira DEX integration for Vultisig SDK - Modular TypeScript SDK for swaps and limit orders on THORChain",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ },
13
+ "./swap": {
14
+ "import": "./dist/modules/swap.js",
15
+ "types": "./dist/modules/swap.d.ts"
16
+ },
17
+ "./orderbook": {
18
+ "import": "./dist/modules/orderbook.js",
19
+ "types": "./dist/modules/orderbook.d.ts"
20
+ },
21
+ "./signer": {
22
+ "import": "./dist/signer/vultisig-provider.js",
23
+ "types": "./dist/signer/vultisig-provider.d.ts"
24
+ },
25
+ "./utils": {
26
+ "import": "./dist/utils/format.js",
27
+ "types": "./dist/utils/format.d.ts"
28
+ },
29
+ "./assets": {
30
+ "import": "./dist/assets/index.js",
31
+ "types": "./dist/assets/index.d.ts"
32
+ }
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "LICENSE"
38
+ ],
39
+ "scripts": {
40
+ "build": "tsc -b",
41
+ "clean": "rm -rf dist",
42
+ "dev": "tsc -w",
43
+ "test": "vitest run",
44
+ "test:watch": "vitest",
45
+ "typecheck": "tsc --noEmit"
46
+ },
47
+ "dependencies": {
48
+ "@bufbuild/protobuf": "^2.10.2",
49
+ "@cosmjs/cosmwasm-stargate": "^0.32.4",
50
+ "@cosmjs/proto-signing": "^0.32.4",
51
+ "@cosmjs/stargate": "^0.32.4",
52
+ "big.js": "^7.0.1",
53
+ "cosmjs-types": "^0.9.0"
54
+ },
55
+ "devDependencies": {
56
+ "@types/big.js": "^6.2.2",
57
+ "@types/node": "^22.13.10",
58
+ "@vultisig/sdk": "0.5.0",
59
+ "typescript": "^5.8.2",
60
+ "vitest": "^3.0.9"
61
+ },
62
+ "peerDependencies": {
63
+ "@vultisig/sdk": ">=0.5.0"
64
+ },
65
+ "peerDependenciesMeta": {
66
+ "@vultisig/sdk": {
67
+ "optional": true
68
+ }
69
+ },
70
+ "keywords": [
71
+ "vultisig",
72
+ "rujira",
73
+ "thorchain",
74
+ "dex",
75
+ "swap",
76
+ "defi",
77
+ "cosmwasm",
78
+ "cosmos",
79
+ "crypto",
80
+ "wallet"
81
+ ],
82
+ "author": "Vultisig",
83
+ "license": "MIT",
84
+ "repository": {
85
+ "type": "git",
86
+ "url": "https://github.com/vultisig/vultisig-sdk.git",
87
+ "directory": "packages/rujira"
88
+ },
89
+ "bugs": {
90
+ "url": "https://github.com/vultisig/vultisig-sdk/issues"
91
+ },
92
+ "engines": {
93
+ "node": ">=20.0.0"
94
+ },
95
+ "publishConfig": {
96
+ "access": "public"
97
+ }
98
+ }
@@ -0,0 +1,47 @@
1
+ # Live Verification Tests
2
+
3
+ Tests that query THORChain mainnet to verify SDK correctness against live data.
4
+
5
+ ## Running Live Tests
6
+
7
+ ```bash
8
+ # Run all live tests
9
+ LIVE_TESTS=1 yarn workspace @vultisig/rujira test
10
+
11
+ # Run specific live test file
12
+ LIVE_TESTS=1 yarn workspace @vultisig/rujira test src/__tests__/orderside-serialization.test.ts
13
+ LIVE_TESTS=1 yarn workspace @vultisig/rujira test src/__tests__/outbound-fee.test.ts
14
+ ```
15
+
16
+ ## Test Files
17
+
18
+ ### `orderside-serialization.test.ts`
19
+ - Verifies FIN contract OrderSide format (base/quote vs buy/sell)
20
+ - Queries live FIN contracts to confirm book structure
21
+ - **Audit Item:** H1
22
+
23
+ ### `outbound-fee.test.ts`
24
+ - Verifies hardcoded fallback fees against THORNode
25
+ - Checks all chain fees are within 3x tolerance
26
+ - **Audit Item:** L2
27
+
28
+ ## When to Run
29
+
30
+ 1. **After updating hardcoded values** - Verify they match mainnet
31
+ 2. **Before releases** - Ensure no regression
32
+ 3. **Periodically** - Detect stale configurations
33
+
34
+ ## Adding New Live Tests
35
+
36
+ Use the `describe.skipIf(!process.env.LIVE_TESTS)` pattern:
37
+
38
+ ```typescript
39
+ describe.skipIf(!process.env.LIVE_TESTS)('Live Test Name', () => {
40
+ it('queries mainnet', async () => {
41
+ const response = await fetch('https://thornode.ninerealms.com/...');
42
+ // assertions
43
+ });
44
+ });
45
+ ```
46
+
47
+ This ensures tests are skipped in normal CI runs but can be enabled explicitly.