@teneo-protocol/sdk 3.1.5 → 3.2.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/README.md +1 -1
- package/dist/core/websocket-client.d.ts +5 -0
- package/dist/core/websocket-client.d.ts.map +1 -1
- package/dist/core/websocket-client.js +51 -37
- package/dist/core/websocket-client.js.map +1 -1
- package/dist/handlers/webhook-handler.d.ts.map +1 -1
- package/dist/handlers/webhook-handler.js +4 -2
- package/dist/handlers/webhook-handler.js.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -3
- package/dist/index.js.map +1 -1
- package/dist/managers/message-router.d.ts +2 -0
- package/dist/managers/message-router.d.ts.map +1 -1
- package/dist/managers/message-router.js +9 -2
- package/dist/managers/message-router.js.map +1 -1
- package/dist/teneo-sdk.d.ts +7 -3
- package/dist/teneo-sdk.d.ts.map +1 -1
- package/dist/teneo-sdk.js +7 -2
- package/dist/teneo-sdk.js.map +1 -1
- package/dist/types/config.d.ts +39 -12
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +22 -0
- package/dist/types/config.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -2
- package/dist/types/index.js.map +1 -1
- package/dist/types/messages.d.ts +65 -6
- package/dist/types/messages.d.ts.map +1 -1
- package/dist/types/messages.js +29 -8
- package/dist/types/messages.js.map +1 -1
- package/dist/utils/erc20.d.ts +65 -0
- package/dist/utils/erc20.d.ts.map +1 -0
- package/dist/utils/erc20.js +116 -0
- package/dist/utils/erc20.js.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +9 -1
- package/dist/utils/index.js.map +1 -1
- package/examples/api-key-payment-flow.ts +103 -0
- package/package.json +1 -1
- package/src/core/websocket-client.ts +60 -39
- package/src/handlers/webhook-handler.ts +4 -2
- package/src/index.ts +8 -1
- package/src/managers/message-router.ts +10 -2
- package/src/teneo-sdk.ts +8 -3
- package/src/types/config.ts +23 -0
- package/src/types/index.ts +1 -0
- package/src/types/messages.ts +38 -8
- package/src/utils/erc20.test.ts +161 -0
- package/src/utils/erc20.ts +125 -0
- package/src/utils/index.ts +10 -0
- package/tsconfig.json +2 -1
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ERC20 utilities for wallet transaction flows.
|
|
3
|
+
*
|
|
4
|
+
* These helpers let SDK consumers check ERC20 token allowances before sending
|
|
5
|
+
* approval transactions, avoiding unnecessary approvals when allowance is
|
|
6
|
+
* already sufficient.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** The 4-byte function selector for ERC20 approve(address,uint256) */
|
|
10
|
+
export const ERC20_APPROVE_SELECTOR = "0x095ea7b3";
|
|
11
|
+
|
|
12
|
+
/** The 4-byte function selector for ERC20 allowance(address,address) */
|
|
13
|
+
const ERC20_ALLOWANCE_SELECTOR = "0xdd62ed3e";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Check if a trigger_wallet_tx calldata is an ERC20 approve call.
|
|
17
|
+
* Returns the spender address if it is, or null otherwise.
|
|
18
|
+
*
|
|
19
|
+
* @param data - The calldata hex string from the trigger_wallet_tx
|
|
20
|
+
* @returns The spender address, or null if not an approve call
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* sdk.on("wallet:tx_requested", async (data) => {
|
|
25
|
+
* const approveInfo = parseApproveCalldata(data.tx.data);
|
|
26
|
+
* if (approveInfo) {
|
|
27
|
+
* // This is an ERC20 approve — check allowance first
|
|
28
|
+
* const allowance = await checkERC20Allowance(rpcUrl, data.tx.to, myAddress, approveInfo.spender);
|
|
29
|
+
* if (allowance >= approveInfo.amount) {
|
|
30
|
+
* // Allowance sufficient for requested amount, skip approval
|
|
31
|
+
* await sdk.sendTxResult(data.taskId, "confirmed", undefined, undefined, data.room, data.tx.chainId);
|
|
32
|
+
* return;
|
|
33
|
+
* }
|
|
34
|
+
* }
|
|
35
|
+
* // Proceed with normal tx signing...
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function parseApproveCalldata(data?: string): { spender: string; amount: bigint } | null {
|
|
40
|
+
if (!data || !data.toLowerCase().startsWith(ERC20_APPROVE_SELECTOR)) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
// approve(address spender, uint256 amount)
|
|
44
|
+
// calldata = 0x095ea7b3 + 32-byte left-padded spender + 32-byte amount
|
|
45
|
+
// Full calldata: "0x" (2) + selector (8) + spender (64) + amount (64) = 138 chars
|
|
46
|
+
if (data.length < 138) return null;
|
|
47
|
+
const spender = "0x" + data.slice(34, 74);
|
|
48
|
+
const amount = BigInt("0x" + data.slice(74, 138));
|
|
49
|
+
return { spender, amount };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Build the eth_call data for checking ERC20 allowance(owner, spender).
|
|
54
|
+
* Returns the hex-encoded calldata string.
|
|
55
|
+
*/
|
|
56
|
+
function buildAllowanceCalldata(owner: string, spender: string): string {
|
|
57
|
+
const ownerHex = owner.toLowerCase().replace("0x", "").padStart(64, "0");
|
|
58
|
+
const spenderHex = spender.toLowerCase().replace("0x", "").padStart(64, "0");
|
|
59
|
+
return ERC20_ALLOWANCE_SELECTOR + ownerHex + spenderHex;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Check the ERC20 allowance for a token via a JSON-RPC eth_call.
|
|
64
|
+
*
|
|
65
|
+
* This is a standalone utility that works with any JSON-RPC endpoint — it does
|
|
66
|
+
* not require wagmi, viem, or ethers. SDK consumers can use this in their
|
|
67
|
+
* `wallet:tx_requested` handler to skip unnecessary approval transactions.
|
|
68
|
+
*
|
|
69
|
+
* @param rpcUrl - The JSON-RPC endpoint URL for the token's chain
|
|
70
|
+
* @param tokenAddress - The ERC20 token contract address
|
|
71
|
+
* @param owner - The token owner (user's wallet address)
|
|
72
|
+
* @param spender - The spender address (from parseApproveCalldata)
|
|
73
|
+
* @returns The allowance as a bigint
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* const allowance = await checkERC20Allowance(
|
|
78
|
+
* "https://mainnet.base.org",
|
|
79
|
+
* "0xA0b8...USDC",
|
|
80
|
+
* userWallet,
|
|
81
|
+
* spenderAddress
|
|
82
|
+
* );
|
|
83
|
+
* if (allowance >= requiredAmount) {
|
|
84
|
+
* console.log("Sufficient allowance, skipping approval");
|
|
85
|
+
* }
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export async function checkERC20Allowance(
|
|
89
|
+
rpcUrl: string,
|
|
90
|
+
tokenAddress: string,
|
|
91
|
+
owner: string,
|
|
92
|
+
spender: string,
|
|
93
|
+
): Promise<bigint> {
|
|
94
|
+
const calldata = buildAllowanceCalldata(owner, spender);
|
|
95
|
+
|
|
96
|
+
const response = await fetch(rpcUrl, {
|
|
97
|
+
method: "POST",
|
|
98
|
+
headers: { "Content-Type": "application/json" },
|
|
99
|
+
body: JSON.stringify({
|
|
100
|
+
jsonrpc: "2.0",
|
|
101
|
+
id: 1,
|
|
102
|
+
method: "eth_call",
|
|
103
|
+
params: [
|
|
104
|
+
{ to: tokenAddress, data: calldata },
|
|
105
|
+
"latest",
|
|
106
|
+
],
|
|
107
|
+
}),
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
if (!response.ok) {
|
|
111
|
+
throw new Error(`RPC request failed with status ${response.status}`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const result = await response.json() as { result?: string; error?: { message: string } };
|
|
115
|
+
|
|
116
|
+
if (result.error) {
|
|
117
|
+
throw new Error(`RPC error: ${result.error.message}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!result.result || result.result === "0x") {
|
|
121
|
+
return 0n;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return BigInt(result.result);
|
|
125
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -79,3 +79,13 @@ export {
|
|
|
79
79
|
type ResolvedPricing,
|
|
80
80
|
type PriceResolutionOptions
|
|
81
81
|
} from "./pricing-resolver";
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* ERC20 utilities for wallet transaction flows.
|
|
85
|
+
* Check allowances to skip unnecessary approval transactions.
|
|
86
|
+
*/
|
|
87
|
+
export {
|
|
88
|
+
checkERC20Allowance,
|
|
89
|
+
parseApproveCalldata,
|
|
90
|
+
ERC20_APPROVE_SELECTOR
|
|
91
|
+
} from "./erc20";
|
package/tsconfig.json
CHANGED
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"strictBindCallApply": true,
|
|
26
26
|
"strictPropertyInitialization": true,
|
|
27
27
|
"noImplicitThis": true,
|
|
28
|
-
"alwaysStrict": true
|
|
28
|
+
"alwaysStrict": true,
|
|
29
|
+
"types": []
|
|
29
30
|
},
|
|
30
31
|
"include": ["src/**/*"],
|
|
31
32
|
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|