context-markets 0.5.0 → 0.6.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 CHANGED
@@ -121,9 +121,9 @@ Prices are in **cents** (1–99). Sizes are in **contracts**. The SDK maps `"yes
121
121
  | Package | Description |
122
122
  |---------|-------------|
123
123
  | **[context-markets](https://github.com/contextwtf/context-sdk)** | TypeScript SDK for trading |
124
- | **[@contextwtf/react](https://github.com/contextwtf/context-react)** | React hooks for market data and trading |
125
- | **[@contextwtf/mcp](https://github.com/contextwtf/context-mcp)** | MCP server for AI agents |
126
- | **[@contextwtf/cli](https://github.com/contextwtf/context-cli)** | CLI for trading from the terminal |
124
+ | **[context-markets-react](https://github.com/contextwtf/context-react)** | React hooks for market data and trading |
125
+ | **[context-markets-mcp](https://github.com/contextwtf/context-mcp)** | MCP server for AI agents |
126
+ | **[context-markets-cli](https://github.com/contextwtf/context-cli)** | CLI for trading from the terminal |
127
127
  | **[context-skills](https://github.com/contextwtf/context-skills)** | AI agent skill files |
128
128
  | **[context-plugin](https://github.com/contextwtf/context-plugin)** | Claude Code plugin |
129
129
 
package/dist/index.cjs CHANGED
@@ -168,6 +168,13 @@ var ERC20_ABI = [
168
168
  { name: "spender", type: "address" }
169
169
  ],
170
170
  outputs: [{ name: "", type: "uint256" }]
171
+ },
172
+ {
173
+ name: "balanceOf",
174
+ type: "function",
175
+ stateMutability: "view",
176
+ inputs: [{ name: "account", type: "address" }],
177
+ outputs: [{ name: "", type: "uint256" }]
171
178
  }
172
179
  ];
173
180
  var HOLDINGS_ABI = [
@@ -206,6 +213,7 @@ var HOLDINGS_ABI = [
206
213
  type: "function",
207
214
  stateMutability: "nonpayable",
208
215
  inputs: [
216
+ { name: "to", type: "address" },
209
217
  { name: "token", type: "address" },
210
218
  { name: "amount", type: "uint256" }
211
219
  ],
@@ -216,6 +224,7 @@ var HOLDINGS_ABI = [
216
224
  type: "function",
217
225
  stateMutability: "nonpayable",
218
226
  inputs: [
227
+ { name: "to", type: "address" },
219
228
  { name: "token", type: "address" },
220
229
  { name: "amount", type: "uint256" }
221
230
  ],
@@ -1013,11 +1022,12 @@ var PortfolioModule = class {
1013
1022
  // src/modules/account.ts
1014
1023
  var import_viem2 = require("viem");
1015
1024
  var AccountModule = class {
1016
- constructor(http2, walletClient, account, chainConfig, rpcUrl) {
1025
+ constructor(http2, walletClient, account, chainConfig, chain, rpcUrl) {
1017
1026
  this.http = http2;
1018
1027
  this.walletClient = walletClient;
1019
1028
  this.account = account;
1020
1029
  this.chainConfig = chainConfig;
1030
+ this.chain = chain;
1021
1031
  this.publicClient = (0, import_viem2.createPublicClient)({
1022
1032
  chain: chainConfig.viemChain,
1023
1033
  transport: (0, import_viem2.http)(rpcUrl)
@@ -1051,8 +1061,14 @@ var AccountModule = class {
1051
1061
  async status() {
1052
1062
  const addr = this.address;
1053
1063
  const { settlement, holdings, usdc } = this.chainConfig;
1054
- const [ethBalance, usdcAllowance, isOperatorApproved] = await Promise.all([
1064
+ const [ethBalance, usdcBalance, usdcAllowance, isOperatorApproved] = await Promise.all([
1055
1065
  this.publicClient.getBalance({ address: addr }),
1066
+ this.publicClient.readContract({
1067
+ address: usdc,
1068
+ abi: ERC20_ABI,
1069
+ functionName: "balanceOf",
1070
+ args: [addr]
1071
+ }),
1056
1072
  this.publicClient.readContract({
1057
1073
  address: usdc,
1058
1074
  abi: ERC20_ABI,
@@ -1066,51 +1082,92 @@ var AccountModule = class {
1066
1082
  args: [addr, settlement]
1067
1083
  })
1068
1084
  ]);
1085
+ const needsUsdcApproval = usdcAllowance === 0n;
1086
+ const needsOperatorApproval = !isOperatorApproved;
1069
1087
  return {
1070
1088
  address: addr,
1071
1089
  ethBalance,
1090
+ usdcBalance,
1072
1091
  usdcAllowance,
1073
1092
  isOperatorApproved,
1074
- needsApprovals: usdcAllowance === 0n || !isOperatorApproved,
1075
- needsGaslessSetup: !isOperatorApproved
1093
+ needsUsdcApproval,
1094
+ needsOperatorApproval,
1095
+ isReady: !needsUsdcApproval && !needsOperatorApproval
1076
1096
  };
1077
1097
  }
1078
- async setup() {
1098
+ // ─── Granular Approval Methods ───
1099
+ async approveUsdc() {
1079
1100
  const wallet = this.requireWallet();
1080
1101
  const account = this.requireAccount();
1081
- const { viemChain, settlement, holdings, usdc } = this.chainConfig;
1082
- const walletStatus = await this.status();
1083
- let usdcApprovalTx = null;
1084
- let operatorApprovalTx = null;
1085
- if (walletStatus.usdcAllowance === 0n) {
1086
- usdcApprovalTx = await wallet.writeContract({
1087
- account,
1088
- chain: viemChain,
1089
- address: usdc,
1090
- abi: ERC20_ABI,
1091
- functionName: "approve",
1092
- args: [holdings, import_viem2.maxUint256]
1093
- });
1094
- }
1095
- if (!walletStatus.isOperatorApproved) {
1096
- operatorApprovalTx = await wallet.writeContract({
1097
- account,
1098
- chain: viemChain,
1099
- address: holdings,
1100
- abi: HOLDINGS_ABI,
1101
- functionName: "setOperator",
1102
- args: [settlement, true]
1103
- });
1104
- }
1105
- return { usdcApprovalTx, operatorApprovalTx };
1102
+ const { viemChain, holdings, usdc } = this.chainConfig;
1103
+ const status = await this.status();
1104
+ if (!status.needsUsdcApproval) return null;
1105
+ const hash = await wallet.writeContract({
1106
+ account,
1107
+ chain: viemChain,
1108
+ address: usdc,
1109
+ abi: ERC20_ABI,
1110
+ functionName: "approve",
1111
+ args: [holdings, import_viem2.maxUint256]
1112
+ });
1113
+ await this.publicClient.waitForTransactionReceipt({ hash });
1114
+ return hash;
1106
1115
  }
1107
- async mintTestUsdc(amount = 1e3) {
1108
- return this.http.post(ENDPOINTS.balance.mintTestUsdc, {
1109
- address: this.address,
1110
- amount: amount.toString()
1116
+ async approveOperator() {
1117
+ const wallet = this.requireWallet();
1118
+ const account = this.requireAccount();
1119
+ const { viemChain, settlement, holdings } = this.chainConfig;
1120
+ const status = await this.status();
1121
+ if (!status.needsOperatorApproval) return null;
1122
+ const hash = await wallet.writeContract({
1123
+ account,
1124
+ chain: viemChain,
1125
+ address: holdings,
1126
+ abi: HOLDINGS_ABI,
1127
+ functionName: "setOperator",
1128
+ args: [settlement, true]
1111
1129
  });
1130
+ await this.publicClient.waitForTransactionReceipt({ hash });
1131
+ return hash;
1132
+ }
1133
+ // ─── Chain-Aware Dispatchers ───
1134
+ async setup() {
1135
+ if (this.chain === "testnet") {
1136
+ const result = await this.gaslessSetup();
1137
+ return {
1138
+ usdcApproval: { needed: false, txHash: null },
1139
+ operatorApproval: { needed: true, txHash: result.txHash }
1140
+ };
1141
+ }
1142
+ return this.onchainSetup();
1112
1143
  }
1113
1144
  async deposit(amount) {
1145
+ if (this.chain === "testnet") {
1146
+ const result = await this.gaslessDeposit(amount);
1147
+ return {
1148
+ txHash: result.txHash,
1149
+ amount: result.amount,
1150
+ gasless: true
1151
+ };
1152
+ }
1153
+ const amountRaw = (0, import_viem2.parseUnits)(amount.toString(), 6);
1154
+ const hash = await this.onchainDeposit(amount);
1155
+ return { txHash: hash, amount: amountRaw.toString(), gasless: false };
1156
+ }
1157
+ // ─── On-Chain Methods ───
1158
+ async onchainSetup() {
1159
+ const status = await this.status();
1160
+ const usdcTx = status.needsUsdcApproval ? await this.approveUsdcUnchecked() : null;
1161
+ const operatorTx = status.needsOperatorApproval ? await this.approveOperatorUnchecked() : null;
1162
+ return {
1163
+ usdcApproval: { needed: status.needsUsdcApproval, txHash: usdcTx },
1164
+ operatorApproval: {
1165
+ needed: status.needsOperatorApproval,
1166
+ txHash: operatorTx
1167
+ }
1168
+ };
1169
+ }
1170
+ async onchainDeposit(amount) {
1114
1171
  const wallet = this.requireWallet();
1115
1172
  const account = this.requireAccount();
1116
1173
  const { viemChain, holdings, usdc } = this.chainConfig;
@@ -1121,7 +1178,7 @@ var AccountModule = class {
1121
1178
  address: holdings,
1122
1179
  abi: HOLDINGS_ABI,
1123
1180
  functionName: "deposit",
1124
- args: [usdc, amountRaw]
1181
+ args: [this.address, usdc, amountRaw]
1125
1182
  });
1126
1183
  await this.publicClient.waitForTransactionReceipt({ hash });
1127
1184
  return hash;
@@ -1137,11 +1194,17 @@ var AccountModule = class {
1137
1194
  address: holdings,
1138
1195
  abi: HOLDINGS_ABI,
1139
1196
  functionName: "withdraw",
1140
- args: [usdc, amountRaw]
1197
+ args: [this.address, usdc, amountRaw]
1141
1198
  });
1142
1199
  await this.publicClient.waitForTransactionReceipt({ hash });
1143
1200
  return hash;
1144
1201
  }
1202
+ async mintTestUsdc(amount = 1e3) {
1203
+ return this.http.post(ENDPOINTS.balance.mintTestUsdc, {
1204
+ address: this.address,
1205
+ amount: amount.toString()
1206
+ });
1207
+ }
1145
1208
  async mintCompleteSets(marketId, amount) {
1146
1209
  const wallet = this.requireWallet();
1147
1210
  const account = this.requireAccount();
@@ -1250,6 +1313,37 @@ var AccountModule = class {
1250
1313
  req
1251
1314
  );
1252
1315
  }
1316
+ // ─── Private helpers (skip status check, used by onchainSetup) ───
1317
+ async approveUsdcUnchecked() {
1318
+ const wallet = this.requireWallet();
1319
+ const account = this.requireAccount();
1320
+ const { viemChain, holdings, usdc } = this.chainConfig;
1321
+ const hash = await wallet.writeContract({
1322
+ account,
1323
+ chain: viemChain,
1324
+ address: usdc,
1325
+ abi: ERC20_ABI,
1326
+ functionName: "approve",
1327
+ args: [holdings, import_viem2.maxUint256]
1328
+ });
1329
+ await this.publicClient.waitForTransactionReceipt({ hash });
1330
+ return hash;
1331
+ }
1332
+ async approveOperatorUnchecked() {
1333
+ const wallet = this.requireWallet();
1334
+ const account = this.requireAccount();
1335
+ const { viemChain, settlement, holdings } = this.chainConfig;
1336
+ const hash = await wallet.writeContract({
1337
+ account,
1338
+ chain: viemChain,
1339
+ address: holdings,
1340
+ abi: HOLDINGS_ABI,
1341
+ functionName: "setOperator",
1342
+ args: [settlement, true]
1343
+ });
1344
+ await this.publicClient.waitForTransactionReceipt({ hash });
1345
+ return hash;
1346
+ }
1253
1347
  };
1254
1348
 
1255
1349
  // src/client.ts
@@ -1261,11 +1355,14 @@ var ContextClient = class {
1261
1355
  account;
1262
1356
  /** The resolved chain configuration. */
1263
1357
  chainConfig;
1358
+ /** Which chain this client is connected to. */
1359
+ chain;
1264
1360
  /** The trader's on-chain address, or null if no signer was provided. */
1265
1361
  address;
1266
1362
  constructor(options = {}) {
1267
1363
  const chainConfig = resolveChainConfig(options.chain);
1268
1364
  this.chainConfig = chainConfig;
1365
+ this.chain = options.chain ?? "mainnet";
1269
1366
  const http2 = createHttpClient({
1270
1367
  apiKey: options.apiKey,
1271
1368
  baseUrl: options.baseUrl ?? chainConfig.apiBase
@@ -1286,7 +1383,7 @@ var ContextClient = class {
1286
1383
  this.questions = new Questions(http2);
1287
1384
  this.orders = new Orders(http2, builder, address);
1288
1385
  this.portfolio = new PortfolioModule(http2, address);
1289
- this.account = new AccountModule(http2, walletClient, account, chainConfig, options.rpcUrl);
1386
+ this.account = new AccountModule(http2, walletClient, account, chainConfig, this.chain, options.rpcUrl);
1290
1387
  }
1291
1388
  };
1292
1389
  // Annotate the CommonJS export names for ESM import in node: