@octaflowlabs/onchain-sdk 1.1.2 → 1.1.4

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.
@@ -3,7 +3,10 @@ import { Transaction } from 'ethers';
3
3
  /** local imports */
4
4
  import { getProvider } from './getProvider';
5
5
  import { errorMessagesForBroadcast, handleErrorMessages } from '../utils/handleErrorMessages';
6
+ import { ensurePublicHost, testJsonRpc } from '../rpc';
6
7
  export const broadcastTransaction = async ({ signedTx, rpcUrl, chainId, waitConfirmations = 0, }) => {
8
+ await ensurePublicHost(rpcUrl);
9
+ await testJsonRpc(rpcUrl, 'eth_chainId', []);
7
10
  const provider = getProvider(rpcUrl, chainId);
8
11
  if (!provider)
9
12
  throw new Error('Could not create provider with given rpcUrl');
@@ -3,7 +3,10 @@ import { Interface, formatUnits, parseUnits } from 'ethers';
3
3
  /** local imports */
4
4
  import { getProvider } from './getProvider';
5
5
  import { estimateGasLimitFromProvider } from './estimateGasLimitFromProvider';
6
+ import { ensurePublicHost, testJsonRpc } from '../rpc';
6
7
  export const buildUnsignedTransferTx = async (options) => {
8
+ await ensurePublicHost(options.rpcUrl);
9
+ await testJsonRpc(options.rpcUrl, 'eth_chainId', []);
7
10
  const provider = getProvider(options.rpcUrl, options.chainId);
8
11
  if (!provider)
9
12
  throw new Error('Could not create provider with given rpcUrl and chainId');
@@ -29,6 +29,12 @@ export const estimateGasLimitFromProvider = async ({ provider, unsignedTx, walle
29
29
  }
30
30
  const bufferPercentage = Math.min(Math.max(Math.round(congestionFactor * 5), 5), 30); // 5% to 30% buffer
31
31
  const newGasLimit = gasEstimated + (gasEstimated * BigInt(bufferPercentage)) / BigInt(100);
32
+ // let suggested: GasFeesApiResponse | undefined = undefined
33
+ // try {
34
+ // suggested = await this.getSuggestedGasPrice((await provider.getNetwork()).chainId)
35
+ // } catch {
36
+ // suggested = undefined
37
+ // }
32
38
  return {
33
39
  gasEstimated,
34
40
  gasLimit: newGasLimit,
@@ -6,7 +6,10 @@ const ethers_1 = require("ethers");
6
6
  /** local imports */
7
7
  const getProvider_1 = require("./getProvider");
8
8
  const handleErrorMessages_1 = require("../utils/handleErrorMessages");
9
+ const rpc_1 = require("../rpc");
9
10
  const broadcastTransaction = async ({ signedTx, rpcUrl, chainId, waitConfirmations = 0, }) => {
11
+ await (0, rpc_1.ensurePublicHost)(rpcUrl);
12
+ await (0, rpc_1.testJsonRpc)(rpcUrl, 'eth_chainId', []);
10
13
  const provider = (0, getProvider_1.getProvider)(rpcUrl, chainId);
11
14
  if (!provider)
12
15
  throw new Error('Could not create provider with given rpcUrl');
@@ -6,7 +6,10 @@ const ethers_1 = require("ethers");
6
6
  /** local imports */
7
7
  const getProvider_1 = require("./getProvider");
8
8
  const estimateGasLimitFromProvider_1 = require("./estimateGasLimitFromProvider");
9
+ const rpc_1 = require("../rpc");
9
10
  const buildUnsignedTransferTx = async (options) => {
11
+ await (0, rpc_1.ensurePublicHost)(options.rpcUrl);
12
+ await (0, rpc_1.testJsonRpc)(options.rpcUrl, 'eth_chainId', []);
10
13
  const provider = (0, getProvider_1.getProvider)(options.rpcUrl, options.chainId);
11
14
  if (!provider)
12
15
  throw new Error('Could not create provider with given rpcUrl and chainId');
@@ -32,6 +32,12 @@ const estimateGasLimitFromProvider = async ({ provider, unsignedTx, walletAddres
32
32
  }
33
33
  const bufferPercentage = Math.min(Math.max(Math.round(congestionFactor * 5), 5), 30); // 5% to 30% buffer
34
34
  const newGasLimit = gasEstimated + (gasEstimated * BigInt(bufferPercentage)) / BigInt(100);
35
+ // let suggested: GasFeesApiResponse | undefined = undefined
36
+ // try {
37
+ // suggested = await this.getSuggestedGasPrice((await provider.getNetwork()).chainId)
38
+ // } catch {
39
+ // suggested = undefined
40
+ // }
35
41
  return {
36
42
  gasEstimated,
37
43
  gasLimit: newGasLimit,
@@ -19,5 +19,9 @@ export { transformBigInt } from './utils/transformBigInt';
19
19
  import NATIVE_TOKENS from './utils/tokens';
20
20
  export { NATIVE_TOKENS };
21
21
  export { formattedAmountForDisplay, parsedAmount } from './utils/formatAmount';
22
+ export { handleErrorMessages, errorMessagesForBroadcast, errorMessagesForGasLimitEstimation, } from './utils/handleErrorMessages';
23
+ export { normalizeAddress } from './utils/normalizeAddress';
24
+ /** rpc exports */
25
+ export { validateRpcUrl, ensurePublicHost, testJsonRpc } from './rpc/index';
22
26
  /** types exports */
23
27
  export { BroadcastTransactionOptions, BuildMaxNativeTransferTxOptions, BuildMaxNativeTransferTxResponse, BuildUnsignedTransferTxOptions, EstimateGasLimitFromProviderProps, GasEstimateResult, TxStatusOptions, TxStatusResponse, UnsignedTransferTxResponse, FormatAmountOptions, TransactionRequest, } from './types/common';
package/dist/cjs/index.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.parsedAmount = exports.formattedAmountForDisplay = exports.NATIVE_TOKENS = exports.transformBigInt = exports.getShortenData = exports.getShortenTransactionHashOrAddress = exports.signTransaction = exports.signMessage = exports.createWallet = exports.EvmWalletService = exports.txStatus = exports.getProvider = exports.estimateGasLimitFromProvider = exports.broadcastTransaction = exports.buildUnsignedTransferTx = exports.buildMaxNativeTransferTx = exports.GAS_LIMIT_PER_TX_TYPE = exports.ERC20_TOKEN_CONTRACT_ABI = void 0;
6
+ exports.testJsonRpc = exports.ensurePublicHost = exports.validateRpcUrl = exports.normalizeAddress = exports.errorMessagesForGasLimitEstimation = exports.errorMessagesForBroadcast = exports.handleErrorMessages = exports.parsedAmount = exports.formattedAmountForDisplay = exports.NATIVE_TOKENS = exports.transformBigInt = exports.getShortenData = exports.getShortenTransactionHashOrAddress = exports.signTransaction = exports.signMessage = exports.createWallet = exports.EvmWalletService = exports.txStatus = exports.getProvider = exports.estimateGasLimitFromProvider = exports.broadcastTransaction = exports.buildUnsignedTransferTx = exports.buildMaxNativeTransferTx = exports.GAS_LIMIT_PER_TX_TYPE = exports.ERC20_TOKEN_CONTRACT_ABI = void 0;
7
7
  /** ABIs exports */
8
8
  const ERC20_TOKEN_CONTRACT_ABI_1 = __importDefault(require("./ABIs/ERC20_TOKEN_CONTRACT_ABI"));
9
9
  exports.ERC20_TOKEN_CONTRACT_ABI = ERC20_TOKEN_CONTRACT_ABI_1.default;
@@ -40,3 +40,14 @@ exports.NATIVE_TOKENS = tokens_1.default;
40
40
  var formatAmount_1 = require("./utils/formatAmount");
41
41
  Object.defineProperty(exports, "formattedAmountForDisplay", { enumerable: true, get: function () { return formatAmount_1.formattedAmountForDisplay; } });
42
42
  Object.defineProperty(exports, "parsedAmount", { enumerable: true, get: function () { return formatAmount_1.parsedAmount; } });
43
+ var handleErrorMessages_1 = require("./utils/handleErrorMessages");
44
+ Object.defineProperty(exports, "handleErrorMessages", { enumerable: true, get: function () { return handleErrorMessages_1.handleErrorMessages; } });
45
+ Object.defineProperty(exports, "errorMessagesForBroadcast", { enumerable: true, get: function () { return handleErrorMessages_1.errorMessagesForBroadcast; } });
46
+ Object.defineProperty(exports, "errorMessagesForGasLimitEstimation", { enumerable: true, get: function () { return handleErrorMessages_1.errorMessagesForGasLimitEstimation; } });
47
+ var normalizeAddress_1 = require("./utils/normalizeAddress");
48
+ Object.defineProperty(exports, "normalizeAddress", { enumerable: true, get: function () { return normalizeAddress_1.normalizeAddress; } });
49
+ /** rpc exports */
50
+ var index_1 = require("./rpc/index");
51
+ Object.defineProperty(exports, "validateRpcUrl", { enumerable: true, get: function () { return index_1.validateRpcUrl; } });
52
+ Object.defineProperty(exports, "ensurePublicHost", { enumerable: true, get: function () { return index_1.ensurePublicHost; } });
53
+ Object.defineProperty(exports, "testJsonRpc", { enumerable: true, get: function () { return index_1.testJsonRpc; } });
@@ -0,0 +1,3 @@
1
+ export declare const validateRpcUrl: (rpcUrl: string, allowLocal?: boolean) => URL;
2
+ export declare const ensurePublicHost: (rpcUrl: string) => Promise<boolean>;
3
+ export declare const testJsonRpc: (rpcUrl: string, method?: string, params?: any[]) => Promise<unknown>;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.testJsonRpc = exports.ensurePublicHost = exports.validateRpcUrl = void 0;
7
+ /** npm imports */
8
+ const promises_1 = __importDefault(require("dns/promises"));
9
+ const net_1 = __importDefault(require("net"));
10
+ const PRIVATE_IP_RANGES = [
11
+ /^127\./,
12
+ /^10\./,
13
+ /^172\.(1[6-9]|2[0-9]|3[0-1])\./,
14
+ /^192\.168\./,
15
+ /^169\.254\./,
16
+ ];
17
+ const validateRpcUrl = (rpcUrl, allowLocal = false) => {
18
+ let url;
19
+ try {
20
+ url = new URL(rpcUrl);
21
+ if (!allowLocal && ['localhost', '127.0.0.1', '::1'].includes(url.hostname))
22
+ throw new Error('Localhost URLs are not allowed');
23
+ }
24
+ catch {
25
+ throw new Error('Invalid RPC URL');
26
+ }
27
+ if (!['http:', 'https:', 'ws:', 'wss:'].includes(url.protocol))
28
+ throw new Error('Unsupported protocol. Only http, https, ws, and wss are allowed.');
29
+ if (['localhost', '127.0.0.1'].includes(url.hostname))
30
+ throw new Error('Localhost RPC not allowed');
31
+ return url;
32
+ };
33
+ exports.validateRpcUrl = validateRpcUrl;
34
+ const ensurePublicHost = async (rpcUrl) => {
35
+ const url = (0, exports.validateRpcUrl)(rpcUrl);
36
+ try {
37
+ const addresses = await promises_1.default.lookup(url.hostname, { all: true });
38
+ const hasPrivateIp = addresses
39
+ .filter((a) => net_1.default.isIP(a.address))
40
+ .some((a) => PRIVATE_IP_RANGES.some((r) => r.test(a.address)));
41
+ if (hasPrivateIp)
42
+ throw new Error('RPC URL resolves to a private IP address');
43
+ return true;
44
+ }
45
+ catch (error) {
46
+ console.error('Error validating RPC URL:', error);
47
+ throw new Error('Failed to validate RPC URL');
48
+ }
49
+ };
50
+ exports.ensurePublicHost = ensurePublicHost;
51
+ const testJsonRpc = async (rpcUrl, method = 'eth_chainId', params = []) => {
52
+ await (0, exports.ensurePublicHost)(rpcUrl);
53
+ const payload = { jsonrpc: '2.0', id: 1, method, params };
54
+ try {
55
+ const res = await fetch(rpcUrl, {
56
+ method: 'POST',
57
+ headers: { 'Content-Type': 'application/json' },
58
+ body: JSON.stringify(payload),
59
+ signal: AbortSignal.timeout(5000),
60
+ });
61
+ const data = await res.json();
62
+ return data;
63
+ }
64
+ catch (error) {
65
+ const errorMessage = error instanceof Error ? error.message : String(error);
66
+ throw new Error(`RPC test failed: ${errorMessage}`);
67
+ }
68
+ };
69
+ exports.testJsonRpc = testJsonRpc;
@@ -0,0 +1 @@
1
+ export declare const normalizeAddress: (address: string) => string;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeAddress = void 0;
4
+ /** npm imports */
5
+ const ethers_1 = require("ethers");
6
+ const normalizeAddress = (address) => {
7
+ try {
8
+ return (0, ethers_1.getAddress)(address);
9
+ }
10
+ catch (e) {
11
+ console.log('Error normalizing address:', e);
12
+ throw new Error('Error normalizing address: ' + (e instanceof Error ? e.message : String(e)));
13
+ }
14
+ };
15
+ exports.normalizeAddress = normalizeAddress;
package/dist/index.d.ts CHANGED
@@ -19,5 +19,9 @@ export { transformBigInt } from './utils/transformBigInt';
19
19
  import NATIVE_TOKENS from './utils/tokens';
20
20
  export { NATIVE_TOKENS };
21
21
  export { formattedAmountForDisplay, parsedAmount } from './utils/formatAmount';
22
+ export { handleErrorMessages, errorMessagesForBroadcast, errorMessagesForGasLimitEstimation, } from './utils/handleErrorMessages';
23
+ export { normalizeAddress } from './utils/normalizeAddress';
24
+ /** rpc exports */
25
+ export { validateRpcUrl, ensurePublicHost, testJsonRpc } from './rpc/index';
22
26
  /** types exports */
23
27
  export { BroadcastTransactionOptions, BuildMaxNativeTransferTxOptions, BuildMaxNativeTransferTxResponse, BuildUnsignedTransferTxOptions, EstimateGasLimitFromProviderProps, GasEstimateResult, TxStatusOptions, TxStatusResponse, UnsignedTransferTxResponse, FormatAmountOptions, TransactionRequest, } from './types/common';
package/dist/index.js CHANGED
@@ -18,3 +18,7 @@ export { transformBigInt } from './utils/transformBigInt';
18
18
  import NATIVE_TOKENS from './utils/tokens';
19
19
  export { NATIVE_TOKENS };
20
20
  export { formattedAmountForDisplay, parsedAmount } from './utils/formatAmount';
21
+ export { handleErrorMessages, errorMessagesForBroadcast, errorMessagesForGasLimitEstimation, } from './utils/handleErrorMessages';
22
+ export { normalizeAddress } from './utils/normalizeAddress';
23
+ /** rpc exports */
24
+ export { validateRpcUrl, ensurePublicHost, testJsonRpc } from './rpc/index';
@@ -0,0 +1,3 @@
1
+ export declare const validateRpcUrl: (rpcUrl: string, allowLocal?: boolean) => URL;
2
+ export declare const ensurePublicHost: (rpcUrl: string) => Promise<boolean>;
3
+ export declare const testJsonRpc: (rpcUrl: string, method?: string, params?: any[]) => Promise<unknown>;
@@ -0,0 +1,60 @@
1
+ /** npm imports */
2
+ import dns from 'dns/promises';
3
+ import net from 'net';
4
+ const PRIVATE_IP_RANGES = [
5
+ /^127\./,
6
+ /^10\./,
7
+ /^172\.(1[6-9]|2[0-9]|3[0-1])\./,
8
+ /^192\.168\./,
9
+ /^169\.254\./,
10
+ ];
11
+ export const validateRpcUrl = (rpcUrl, allowLocal = false) => {
12
+ let url;
13
+ try {
14
+ url = new URL(rpcUrl);
15
+ if (!allowLocal && ['localhost', '127.0.0.1', '::1'].includes(url.hostname))
16
+ throw new Error('Localhost URLs are not allowed');
17
+ }
18
+ catch {
19
+ throw new Error('Invalid RPC URL');
20
+ }
21
+ if (!['http:', 'https:', 'ws:', 'wss:'].includes(url.protocol))
22
+ throw new Error('Unsupported protocol. Only http, https, ws, and wss are allowed.');
23
+ if (['localhost', '127.0.0.1'].includes(url.hostname))
24
+ throw new Error('Localhost RPC not allowed');
25
+ return url;
26
+ };
27
+ export const ensurePublicHost = async (rpcUrl) => {
28
+ const url = validateRpcUrl(rpcUrl);
29
+ try {
30
+ const addresses = await dns.lookup(url.hostname, { all: true });
31
+ const hasPrivateIp = addresses
32
+ .filter((a) => net.isIP(a.address))
33
+ .some((a) => PRIVATE_IP_RANGES.some((r) => r.test(a.address)));
34
+ if (hasPrivateIp)
35
+ throw new Error('RPC URL resolves to a private IP address');
36
+ return true;
37
+ }
38
+ catch (error) {
39
+ console.error('Error validating RPC URL:', error);
40
+ throw new Error('Failed to validate RPC URL');
41
+ }
42
+ };
43
+ export const testJsonRpc = async (rpcUrl, method = 'eth_chainId', params = []) => {
44
+ await ensurePublicHost(rpcUrl);
45
+ const payload = { jsonrpc: '2.0', id: 1, method, params };
46
+ try {
47
+ const res = await fetch(rpcUrl, {
48
+ method: 'POST',
49
+ headers: { 'Content-Type': 'application/json' },
50
+ body: JSON.stringify(payload),
51
+ signal: AbortSignal.timeout(5000),
52
+ });
53
+ const data = await res.json();
54
+ return data;
55
+ }
56
+ catch (error) {
57
+ const errorMessage = error instanceof Error ? error.message : String(error);
58
+ throw new Error(`RPC test failed: ${errorMessage}`);
59
+ }
60
+ };
@@ -0,0 +1 @@
1
+ export declare const normalizeAddress: (address: string) => string;
@@ -0,0 +1,11 @@
1
+ /** npm imports */
2
+ import { getAddress } from 'ethers';
3
+ export const normalizeAddress = (address) => {
4
+ try {
5
+ return getAddress(address);
6
+ }
7
+ catch (e) {
8
+ console.log('Error normalizing address:', e);
9
+ throw new Error('Error normalizing address: ' + (e instanceof Error ? e.message : String(e)));
10
+ }
11
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@octaflowlabs/onchain-sdk",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "onchain methods for web3",
5
5
  "repository": "https://github.com/crisramb665/onchain-sdk.git",
6
6
  "license": "MIT",
@@ -16,6 +16,7 @@
16
16
  "prepublishOnly": "yarn run build"
17
17
  },
18
18
  "devDependencies": {
19
+ "@types/node": "^25.2.2",
19
20
  "eslint": "^9.39.2",
20
21
  "eslint-config-prettier": "^10.1.8",
21
22
  "eslint-plugin-prettier": "^5.5.5",