diff --git a/.github/workflows/size-limit.yml b/.github/workflows/size-limit.yml new file mode 100644 index 0000000..7ea440f --- /dev/null +++ b/.github/workflows/size-limit.yml @@ -0,0 +1,25 @@ +name: Bundle Size + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + size-limit: + name: Size limit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + + - run: npm ci + - run: npm run build + + - name: Check bundle size + run: npx size-limit diff --git a/.size-limit.json b/.size-limit.json new file mode 100644 index 0000000..834166d --- /dev/null +++ b/.size-limit.json @@ -0,0 +1,34 @@ +[ + { + "path": [ + "dist/esm/index.js", + "dist/esm/chunks/*.js" + ], + "limit": "80 KB", + "gzip": true + }, + { + "path": [ + "dist/cjs/index.js", + "dist/cjs/chunks/*.js" + ], + "limit": "80 KB", + "gzip": true + }, + { + "path": [ + "dist/esm/utils.js", + "dist/esm/chunks/*.js" + ], + "limit": "30 KB", + "gzip": true + }, + { + "path": [ + "dist/cjs/utils.js", + "dist/cjs/chunks/*.js" + ], + "limit": "30 KB", + "gzip": true + } +] diff --git a/README.md b/README.md index 9e19889..7635fba 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,18 @@ const client = new ConduitClient(config: ConduitConfig); | `rpcUrl` | `string` | No | Override default Soroban RPC URL | | `factoryAddress` | `string` | No | Override deployed factory contract ID | | `governorAddress` | `string` | No | Override deployed governor contract ID | +| `fee` | `string` | No | Explicit inclusion fee in stroops (overrides feeMultiplier) | +| `feeMultiplier` | `number` | No | Multiplier applied to BASE_FEE when fee is not set | + +### Fee Precedence + +When both `fee` and `feeMultiplier` are present, `fee` wins. The precedence is: + +1. **`fee`** — explicit inclusion fee in stroops (e.g. `"5000"`) +2. **`feeMultiplier`** — multiplied by `BASE_FEE` when `fee` is absent +3. **`BASE_FEE`** — hardcoded fallback when neither is set + +Use `resolveFee(config)` to compute the effective fee for a given `ConduitConfig`. ### WalletConnect v2 Integration (Mobile & Browser Wallets) diff --git a/package-lock.json b/package-lock.json index eb86a5c..34cf2b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^1.0.0", "@rollup/plugin-typescript": "^11.1.6", + "@size-limit/file": "11.2.0", "@stellar/stellar-sdk": "^12.0.0", "@types/node": "^20.14.0", "@typescript-eslint/eslint-plugin": "^7.14.0", @@ -25,6 +26,7 @@ "playwright": "^1.62.0", "rollup": "^4.18.0", "rollup-plugin-visualizer": "^7.0.1", + "size-limit": "11.2.0", "typescript": "^5.5.3", "vitest": "^4.1.10" }, @@ -1120,6 +1122,19 @@ "win32" ] }, + "node_modules/@size-limit/file": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@size-limit/file/-/file-11.2.0.tgz", + "integrity": "sha512-OZHE3putEkQ/fgzz3Tp/0hSmfVo3wyTpOJSRNm6AmcwX4Nm9YtTfbQQ/hZRwbBFR23S7x2Sd9EbqYzngKwbRoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "size-limit": "11.2.0" + } + }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", @@ -1906,6 +1921,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bytes-iec": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes-iec/-/bytes-iec-3.1.1.tgz", + "integrity": "sha512-fey6+4jDK7TFtFg/klGSvNKJctyU7n2aQdnM+CO0ruLPbqqMOM8Tio0Pc+deqUeVKX1tL5DQep1zQ7+37aTAsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/call-bind": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", @@ -1993,6 +2018,22 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/cliui": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", @@ -3352,6 +3393,16 @@ "node": ">=8" } }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/js-tokens": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", @@ -3688,6 +3739,19 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3861,6 +3925,16 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/nanospinner": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/nanospinner/-/nanospinner-1.2.2.tgz", + "integrity": "sha512-Zt/AmG6qRU3e+WnzGGLuMCEAO/dAu45stNbHY223tUxldaDAeE+FxSPsd9Q+j+paejmm0ZbrNVs5Sraqy3dRxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.1.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -4195,6 +4269,20 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/require-addon": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/require-addon/-/require-addon-1.2.0.tgz", @@ -4529,6 +4617,28 @@ "dev": true, "license": "ISC" }, + "node_modules/size-limit": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/size-limit/-/size-limit-11.2.0.tgz", + "integrity": "sha512-2kpQq2DD/pRpx3Tal/qRW1SYwcIeQ0iq8li5CJHQgOC+FtPn2BVmuDtzUCgNnpCrbgtfEHqh+iWzxK+Tq6C+RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes-iec": "^3.1.1", + "chokidar": "^4.0.3", + "jiti": "^2.4.2", + "lilconfig": "^3.1.3", + "nanospinner": "^1.2.2", + "picocolors": "^1.1.1", + "tinyglobby": "^0.2.11" + }, + "bin": { + "size-limit": "bin.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -4714,9 +4824,9 @@ } }, "node_modules/terser": { - "version": "5.49.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.49.0.tgz", - "integrity": "sha512-SNiDnXyHSrxVcIOtVbULzcTmniUiwcV7Nwdyj1twVubeTmbjoa8p69KKDpfkdoOavuM4/GRm1+ykI8qqnavHoA==", + "version": "5.51.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.51.2.tgz", + "integrity": "sha512-bWnjSNscmuI+GJze6ZupnHP8G/cTcsJF+bXCeQknk2SHQsgbNJnLrqiH9jZ2W4STPVXH2mDKKRX3iwPhc9Cn/Q==", "dev": true, "license": "BSD-2-Clause", "dependencies": { diff --git a/package.json b/package.json index ca264fc..748d1b9 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,21 @@ "require": "./dist/cjs/index.js", "types": "./dist/types/index.d.ts" }, + "./indexer": { + "import": "./dist/esm/indexer.js", + "require": "./dist/cjs/indexer.js", + "types": "./dist/types/indexer.d.ts" + }, + "./batch": { + "import": "./dist/esm/batch-tx.js", + "require": "./dist/cjs/batch-tx.js", + "types": "./dist/types/batch-tx.d.ts" + }, + "./nonce": { + "import": "./dist/esm/nonce/NonceManager.js", + "require": "./dist/cjs/nonce/NonceManager.js", + "types": "./dist/types/nonce/NonceManager.d.ts" + }, "./utils": { "import": "./dist/esm/utils.js", "require": "./dist/cjs/utils.js", @@ -47,6 +62,7 @@ "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^1.0.0", "@rollup/plugin-typescript": "^11.1.6", + "@size-limit/file": "11.2.0", "@stellar/stellar-sdk": "^12.0.0", "@types/node": "^20.14.0", "@typescript-eslint/eslint-plugin": "^7.14.0", @@ -56,6 +72,7 @@ "playwright": "^1.62.0", "rollup": "^4.18.0", "rollup-plugin-visualizer": "^7.0.1", + "size-limit": "11.2.0", "typescript": "^5.5.3", "vitest": "^4.1.10" }, diff --git a/src/index.ts b/src/index.ts index 0600c69..a69e711 100644 --- a/src/index.ts +++ b/src/index.ts @@ -69,7 +69,7 @@ export { } from './utils.js'; // RPC server lifecycle -export { getServer, clearServerCache } from './soroban.js'; +export { getServer, clearServerCache, resolveFee } from './soroban.js'; export { getTokenDecimals, clearTokenDecimalsCache } from './soroban.js'; export {