@net-protocol/relay 0.1.2 → 0.1.3

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/dist/index.d.mts CHANGED
@@ -137,6 +137,8 @@ interface FundBackendWalletParams {
137
137
  txHash?: string;
138
138
  } | null;
139
139
  };
140
+ /** Optional custom USDC amount. If not provided, uses default minimum. */
141
+ amount?: number;
140
142
  }
141
143
  /**
142
144
  * Parameters for submitting transactions via relay
@@ -368,6 +370,8 @@ declare class RelayClient {
368
370
  secretKey: string;
369
371
  fetchWithPayment: typeof fetch;
370
372
  httpClient: FundBackendWalletParams["httpClient"];
373
+ /** Optional custom USDC amount. If not provided, uses default minimum. */
374
+ amount?: number;
371
375
  }): Promise<RelayFundResult>;
372
376
  /**
373
377
  * Submit transactions via relay
package/dist/index.d.ts CHANGED
@@ -137,6 +137,8 @@ interface FundBackendWalletParams {
137
137
  txHash?: string;
138
138
  } | null;
139
139
  };
140
+ /** Optional custom USDC amount. If not provided, uses default minimum. */
141
+ amount?: number;
140
142
  }
141
143
  /**
142
144
  * Parameters for submitting transactions via relay
@@ -368,6 +370,8 @@ declare class RelayClient {
368
370
  secretKey: string;
369
371
  fetchWithPayment: typeof fetch;
370
372
  httpClient: FundBackendWalletParams["httpClient"];
373
+ /** Optional custom USDC amount. If not provided, uses default minimum. */
374
+ amount?: number;
371
375
  }): Promise<RelayFundResult>;
372
376
  /**
373
377
  * Submit transactions via relay
package/dist/index.js CHANGED
@@ -185,13 +185,18 @@ async function fundBackendWallet(params) {
185
185
  secretKey,
186
186
  fetchWithPayment,
187
187
  httpClient,
188
- chainId
188
+ chainId,
189
+ amount
189
190
  } = params;
190
- const fundUrl = `${apiUrl}/api/relay/${chainId}/fund`;
191
+ let fundUrl = `${apiUrl}/api/relay/${chainId}/fund`;
192
+ if (amount !== void 0 && amount > 0) {
193
+ fundUrl += `?amount=${amount}`;
194
+ }
191
195
  console.log("\u{1F4B0} Funding backend wallet", {
192
196
  url: fundUrl,
193
197
  chainId,
194
198
  operatorAddress,
199
+ amount: amount !== void 0 ? `$${amount.toFixed(2)}` : "default",
195
200
  facilitator: chainId === 8453 ? "Coinbase CDP (Base Mainnet)" : chainId === 84532 ? "x402.org (Base Sepolia)" : "unknown"
196
201
  });
197
202
  let fundResponse;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/session.ts","../src/balance.ts","../src/fund.ts","../src/submit.ts","../src/retry.ts","../src/batch.ts","../src/confirmations.ts","../src/client/x402Client.ts","../src/client/RelayClient.ts"],"names":["keccak256","toBytes","waitForTransactionReceipt","client","x402Client","registerExactEvmScheme","wrapFetchWithPayment","x402HTTPClient"],"mappings":";;;;;;;;;;AAKO,IAAM,iBAAA,GAAoB;AAK1B,IAAM,oBAAA,GAAuB;AAK7B,IAAM,mBAAA,GAAsB;AAAA,EACjC,YAAA,EAAc;AAAA,IACZ,EAAE,IAAA,EAAM,iBAAA,EAAmB,IAAA,EAAM,SAAA,EAAU;AAAA,IAC3C,EAAE,IAAA,EAAM,eAAA,EAAiB,IAAA,EAAM,SAAA,EAAU;AAAA,IACzC,EAAE,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,SAAA;AAAU;AAEzC;AAKO,IAAM,oBAAA,GAA8C;AAAA,EACzD,UAAA,EAAY,CAAA;AAAA,EACZ,YAAA,EAAc,GAAA;AAAA,EACd,QAAA,EAAU,GAAA;AAAA,EACV,iBAAA,EAAmB;AACrB;AAKO,IAAM,qBAAA,GAAwB;AAK9B,IAAM,eAAA,GAAkB;AAKxB,IAAM,0BAAA,GAA6B;AAKnC,IAAM,uBAAuB,GAAA,GAAM;AAOnC,IAAM,6BAA6B,GAAA,GAAM;;;ACvChD,eAAsB,mBAAmB,MAAA,EAOgB;AACvD,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAS,iBAAiB,SAAA,EAAW,OAAA,EAAS,WAAU,GACtE,MAAA;AAEF,EAAA,MAAM,mBAAmB,SAAA,IAAa,IAAA;AACtC,EAAA,MAAM,YAAY,IAAA,CAAK,KAAA,CAAM,KAAK,GAAA,EAAI,GAAI,GAAI,CAAA,GAAI,gBAAA;AAClD,EAAA,MAAM,aAAA,GAAgBA,cAAA,CAAUC,YAAA,CAAQ,SAAS,CAAC,CAAA;AAElD,EAAA,MAAM,MAAA,GAAS;AAAA,IACb,IAAA,EAAM,iBAAA;AAAA,IACN,OAAA,EAAS,oBAAA;AAAA,IACT;AAAA,GACF;AAEA,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,eAAA;AAAA,IACA,aAAA;AAAA,IACA,SAAA,EAAW,OAAO,SAAS;AAAA,GAC7B;AAGA,EAAA,MAAM,SAAA,GAAY,MAAM,OAAA,CAAQ,aAAA,CAAc;AAAA,IAC5C,MAAA;AAAA,IACA,KAAA,EAAO,mBAAA;AAAA,IACP,WAAA,EAAa,cAAA;AAAA,IACb;AAAA,GACD,CAAA;AAGD,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA,kBAAA,CAAA,EAAsB;AAAA,IAC1D,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB;AAAA,KAClB;AAAA,IACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,MACnB,OAAA;AAAA,MACA,eAAA;AAAA,MACA,SAAA;AAAA,MACA,SAAA;AAAA,MACA;AAAA;AAAA,KACD;AAAA,GACF,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,SAAA,GAAa,MAAM,QAAA,CAAS,IAAA,EAAK;AACvC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,4BAA4B,QAAA,CAAS,MAAM,IACzC,SAAA,CAAU,KAAA,IAAS,SAAS,UAC9B,CAAA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAU,MAAM,QAAA,CAAS,IAAA,EAAK;AAGpC,EAAA,IAAI,CAAC,MAAA,CAAO,OAAA,IAAW,OAAA,IAAW,MAAA,EAAQ;AACxC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,6BACG,OAAA,IAAW,MAAA,GAAS,MAAA,CAAO,KAAA,GAAQ,SAAS,eAC/C,CAAA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,MAAA,CAAO,YAAA,IAAgB,CAAC,OAAO,SAAA,EAAW;AAC7C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,cAAc,MAAA,CAAO,YAAA;AAAA,IACrB,WAAW,MAAA,CAAO;AAAA,GACpB;AACF;;;ACjFA,eAAsB,0BACpB,MAAA,EAC6B;AAC7B,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAS,eAAA,EAAiB,WAAU,GAAI,MAAA;AAExD,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA,kBAAA,CAAA,EAAsB;AAAA,IAC1D,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB;AAAA,KAClB;AAAA,IACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,MACnB,OAAA;AAAA,MACA,eAAA;AAAA,MACA;AAAA,KACD;AAAA,GACF,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,SAAA,GAAa,MAAM,QAAA,CAAS,IAAA,EAAK;AACvC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,+BAAA,EAAkC,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA;AAAA,QACxD;AAAA,OACD,CAAA;AAAA,KACH;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAU,MAAM,QAAA,CAAS,IAAA,EAAK;AACpC,EAAA,IAAI,CAAC,MAAA,CAAO,OAAA,IAAW,OAAA,IAAW,MAAA,EAAQ;AACxC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,0BAA0B,OAAA,IAAW,MAAA,GAAS,MAAA,CAAO,KAAA,GAAQ,SAAS,eAAe,CAAA;AAAA,KACvF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,sBAAsB,MAAA,CAAO,oBAAA;AAAA,IAC7B,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,mBAAmB,MAAA,CAAO,iBAAA;AAAA,IAC1B,gBAAgB,MAAA,CAAO,cAAA;AAAA,IACvB,gBAAgB,MAAA,CAAO;AAAA,GACzB;AACF;;;AC/CA,SAAS,oBAAA,CACP,UACA,UAAA,EACe;AACf,EAAA,IAAI;AACF,IAAA,MAAM,kBAAkB,UAAA,CAAW,wBAAA;AAAA,MACjC,CAAC,IAAA,KAAiB,QAAA,CAAS,OAAA,CAAQ,IAAI,IAAI;AAAA,KAC7C;AACA,IAAA,OAAO,eAAA,EAAiB,WAAA,IAAe,eAAA,EAAiB,MAAA,IAAU,IAAA;AAAA,EACpE,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,+CAA+C,KAAK,CAAA;AAClE,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAKA,SAAS,sBAAA,CACP,YACA,YAAA,EACS;AAET,EAAA,IAAI,UAAA,IAAc,KAAK,OAAO,IAAA;AAG9B,EAAA,IAAI,UAAA,IAAc,GAAA,IAAO,UAAA,GAAa,GAAA,EAAK;AACzC,IAAA,MAAM,GAAA,GAAM,aAAa,WAAA,EAAY;AACrC,IAAA,OACE,GAAA,CAAI,QAAA,CAAS,qCAAqC,CAAA,IAClD,GAAA,CAAI,SAAS,0CAA0C,CAAA,IACvD,GAAA,CAAI,QAAA,CAAS,gBAAgB,CAAA;AAAA,EAEjC;AAEA,EAAA,OAAO,KAAA;AACT;AAKA,eAAe,mBAAA,CACb,MAAA,EACA,aAAA,EACA,eAAA,EACA,WACA,OAAA,EAC6B;AAC7B,EAAA,MAAM,UAAA,GAAa,CAAA;AACnB,EAAA,MAAM,cAAA,GAAiB,GAAA;AAEvB,EAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,UAAA,EAAY,OAAA,EAAA,EAAW;AACtD,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA,sBAAA,CAAA,EAA0B;AAAA,MAC9D,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,OAAA;AAAA,QACA,aAAA;AAAA,QACA,eAAA;AAAA,QACA;AAAA,OACD;AAAA,KACF,CAAA;AAED,IAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAElC,IAAA,IAAI,QAAA,CAAS,EAAA,IAAM,IAAA,CAAK,OAAA,EAAS;AAC/B,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,YAAA,GAAgB,KAAuB,KAAA,IAAS,eAAA;AAGtD,IAAA,IAAI,CAAC,sBAAA,CAAuB,QAAA,CAAS,MAAA,EAAQ,YAAY,CAAA,EAAG;AAC1D,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,SAAS,MAAM,CAAA,CAAA,EAAI,YAAY,CAAA,CAAE,CAAA;AAAA,IAC1E;AAGA,IAAA,IAAI,YAAY,UAAA,EAAY;AAC1B,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,yBAAA,EAA4B,UAAA,GAAa,CAAC,CAAA,WAAA,EAAc,YAAY,CAAA;AAAA,OACtE;AAAA,IACF;AAGA,IAAA,MAAM,OAAA,GAAU,cAAA,GAAiB,IAAA,CAAK,GAAA,CAAI,GAAG,OAAO,CAAA;AACpD,IAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA,EAC7D;AAEA,EAAA,MAAM,IAAI,MAAM,iCAAiC,CAAA;AACnD;AAgBA,eAAsB,kBACpB,MAAA,EAC0B;AAC1B,EAAA,MAAM;AAAA,IACJ,MAAA;AAAA,IACA,eAAA;AAAA,IACA,SAAA;AAAA,IACA,gBAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF,GAAI,MAAA;AAEJ,EAAA,MAAM,OAAA,GAAU,CAAA,EAAG,MAAM,CAAA,WAAA,EAAc,OAAO,CAAA,KAAA,CAAA;AAE9C,EAAA,OAAA,CAAQ,IAAI,kCAAA,EAA6B;AAAA,IACvC,GAAA,EAAK,OAAA;AAAA,IACL,OAAA;AAAA,IACA,eAAA;AAAA,IACA,aACE,OAAA,KAAY,IAAA,GACR,6BAAA,GACA,OAAA,KAAY,QACZ,yBAAA,GACA;AAAA,GACP,CAAA;AAGD,EAAA,IAAI,YAAA;AACJ,EAAA,IAAI;AACF,IAAA,YAAA,GAAe,MAAM,iBAAiB,OAAA,EAAS;AAAA,MAC7C,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB;AAAA,OAClB;AAAA,MACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,OAAA;AAAA,QACA,eAAA;AAAA,QACA;AAAA,OACD;AAAA,KACF,CAAA;AAAA,EACH,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,MAAM,4BAAA,EAAyB;AAAA,MACrC,OAAO,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAAA,MAC5D,OAAA;AAAA,MACA,GAAA,EAAK;AAAA,KACN,CAAA;AACD,IAAA,MAAM,KAAA;AAAA,EACR;AAEA,EAAA,MAAM,QAAA,GAAY,MAAM,YAAA,CAAa,IAAA,EAAK;AAG1C,EAAA,IAAI,YAAA,CAAa,WAAW,GAAA,EAAK;AAE/B,IAAA,IAAI,OAAA,IAAW,QAAA,IAAY,QAAA,CAAS,KAAA,EAAO,CAE3C,MAAA,IAAW,SAAA,IAAa,QAAA,IAAY,QAAA,CAAS,OAAA,EAAS,CAEtD,MAAO;AACL,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,gDAAgD,IAAA,CAAK,SAAA;AAAA,UACnD;AAAA,SACD,CAAA;AAAA,OACH;AAAA,IACF;AAAA,EACF,CAAA,MAAA,IAAW,CAAC,YAAA,CAAa,EAAA,EAAI;AAC3B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,yBAAyB,YAAA,CAAa,MAAM,IAAI,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAC,CAAA;AAAA,KAC1E;AAAA,EACF;AAGA,EAAA,MAAM,aAAA,GAAgB,oBAAA,CAAqB,YAAA,EAAc,UAAU,CAAA;AAEnE,EAAA,IAAI,CAAC,aAAA,EAAe;AAClB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAGA,EAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,GAAI,CAAC,CAAA;AAGxD,EAAA,MAAM,aAAa,MAAM,mBAAA;AAAA,IACvB,MAAA;AAAA,IACA,aAAA;AAAA,IACA,eAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAA,CAAQ,IAAI,mDAAA,EAAgD;AAAA,IAC1D,sBAAsB,UAAA,CAAW;AAAA,GAClC,CAAA;AAED,EAAA,IAAI,CAAC,WAAW,oBAAA,EAAsB;AACpC,IAAA,MAAM,IAAI,MAAM,qDAAqD,CAAA;AAAA,EACvE;AAEA,EAAA,OAAO;AAAA,IACL,aAAA;AAAA,IACA,sBAAsB,UAAA,CAAW;AAAA,GACnC;AACF;;;AC3MA,eAAsB,2BACpB,MAAA,EAC4B;AAC5B,EAAA,MAAM;AAAA,IACJ,MAAA;AAAA,IACA,OAAA;AAAA,IACA,eAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACF,GAAI,MAAA;AAEJ,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA,iBAAA,CAAA,EAAqB;AAAA,IACzD,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB;AAAA,KAClB;AAAA,IACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,MACnB,OAAA;AAAA,MACA,eAAA;AAAA,MACA,SAAA;AAAA,MACA,YAAA,EAAc,YAAA,CAAa,GAAA,CAAI,CAAC,EAAA,MAAQ;AAAA,QACtC,GAAG,EAAA;AAAA;AAAA,QAEH,GAAI,EAAA,CAAG,KAAA,KAAU,MAAA,IAAa,EAAA,CAAG,QAAQ,MAAA,CAAO,CAAC,CAAA,GAC7C,EAAE,OAAO,EAAA,CAAG,KAAA,CAAM,QAAA,EAAS,KAC3B;AAAC,OACP,CAAE,CAAA;AAAA,MACF;AAAA,KACD;AAAA,GACF,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,SAAA,GAAa,MAAM,QAAA,CAAS,IAAA,EAAK;AACvC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,8BAAA,EAAiC,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA;AAAA,QACvD;AAAA,OACD,CAAA;AAAA,KACH;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAU,MAAM,QAAA,CAAS,IAAA,EAAK;AACpC,EAAA,IAAI,CAAC,MAAA,CAAO,OAAA,IAAW,OAAA,IAAW,MAAA,EAAQ;AACxC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,yBACG,OAAA,IAAW,MAAA,GAAS,MAAA,CAAO,KAAA,GAAQ,SAAS,eAC/C,CAAA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,mBAAmB,MAAA,CAAO,iBAAA,CAAkB,GAAA,CAAI,CAAC,MAAc,CAAS,CAAA;AAAA,IACxE,iBAAA,EAAmB,MAAA,CAAO,iBAAA,IAAqB,EAAC;AAAA,IAChD,aAAA,EAAe,MAAA,CAAO,aAAA,IAAiB,EAAC;AAAA,IACxC,MAAA,EAAQ,MAAA,CAAO,MAAA,IAAU,EAAC;AAAA,IAC1B,sBAAsB,MAAA,CAAO,oBAAA;AAAA,IAC7B,uBAAuB,MAAA,CAAO;AAAA,GAChC;AACF;;;AC/DA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD;AAKA,SAAS,cAAA,CACP,SACA,MAAA,EACQ;AACR,EAAA,MAAM,QACJ,MAAA,CAAO,YAAA,GAAe,KAAK,GAAA,CAAI,MAAA,CAAO,mBAAmB,OAAO,CAAA;AAClE,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,MAAA,CAAO,QAAQ,CAAA;AACxC;AAcA,eAAsB,wBACpB,MAAA,EAC4B;AAC5B,EAAA,MAAM;AAAA,IACJ,MAAA;AAAA,IACA,OAAA;AAAA,IACA,eAAA;AAAA,IACA,SAAA;AAAA,IACA,aAAA,EAAe,oBAAA;AAAA,IACf,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,SAAS,EAAC;AAAA,IACV,YAAA;AAAA,IACA;AAAA,GACF,GAAI,MAAA;AAEJ,EAAA,MAAM,WAAA,GAAqC;AAAA,IACzC,GAAG,oBAAA;AAAA,IACH,GAAG;AAAA,GACL;AAEA,EAAA,IAAI,aAAA,GAAgB,oBAAA;AACpB,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,IAAI,UAAA,GAAuC,IAAA;AAE3C,EAAA,OAAO,aAAA,CAAc,MAAA,GAAS,CAAA,IAAK,OAAA,GAAU,YAAY,UAAA,EAAY;AACnE,IAAA,OAAA,EAAA;AAGA,IAAA,IAAI,eAAA,EAAiB;AACnB,MAAA,aAAA,GAAgB,MAAM,eAAA;AAAA,QACpB,aAAA;AAAA,QACA,oBAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAE9B,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,OAAA,GAAU,CAAA,EAAG,WAAW,CAAA;AACrD,IAAA,IAAI,UAAU,CAAA,EAAG;AAEf,MAAA,MAAM,MAAM,KAAK,CAAA;AAAA,IACnB;AAGA,IAAA,MAAM,qBAAqB,aAAA,CAAc,GAAA;AAAA,MACvC,CAAC,GAAA,KAAQ,oBAAA,CAAqB,GAAG;AAAA,KACnC;AAGA,IAAA,IAAI;AACF,MAAA,MAAM,WAAA,GAAc,MAAM,0BAAA,CAA2B;AAAA,QACnD,MAAA;AAAA,QACA,OAAA;AAAA,QACA,eAAA;AAAA,QACA,SAAA;AAAA,QACA,YAAA,EAAc,kBAAA;AAAA,QACd;AAAA,OACD,CAAA;AAGD,MAAA,IAAI,UAAA,EAAY;AAEd,QAAA,UAAA,CAAW,iBAAA,CAAkB,IAAA,CAAK,GAAG,WAAA,CAAY,iBAAiB,CAAA;AAElE,QAAA,UAAA,CAAW,iBAAA,CAAkB,IAAA;AAAA,UAC3B,GAAG,YAAY,iBAAA,CAAkB,GAAA,CAAI,CAAC,GAAA,KAAQ,aAAA,CAAc,GAAG,CAAC;AAAA,SAClE;AAEA,QAAA,UAAA,CAAW,aAAA,GAAgB,YAAY,aAAA,CAAc,GAAA;AAAA,UACnD,CAAC,GAAA,KAAQ,aAAA,CAAc,GAAG;AAAA,SAC5B;AAEA,QAAA,UAAA,CAAW,MAAA,CAAO,IAAA;AAAA,UAChB,GAAG,WAAA,CAAY,MAAA,CAAO,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,YAClC,KAAA,EAAO,aAAA,CAAc,GAAA,CAAI,KAAK,CAAA;AAAA,YAC9B,OAAO,GAAA,CAAI;AAAA,WACb,CAAE;AAAA,SACJ;AAAA,MACF,CAAA,MAAO;AACL,QAAA,UAAA,GAAa;AAAA,UACX,GAAG,WAAA;AAAA,UACH,iBAAA,EAAmB,YAAY,iBAAA,CAAkB,GAAA;AAAA,YAC/C,CAAC,GAAA,KAAQ,aAAA,CAAc,GAAG;AAAA,WAC5B;AAAA,UACA,aAAA,EAAe,YAAY,aAAA,CAAc,GAAA;AAAA,YACvC,CAAC,GAAA,KAAQ,aAAA,CAAc,GAAG;AAAA,WAC5B;AAAA,UACA,MAAA,EAAQ,WAAA,CAAY,MAAA,CAAO,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,YACvC,KAAA,EAAO,aAAA,CAAc,GAAA,CAAI,KAAK,CAAA;AAAA,YAC9B,OAAO,GAAA,CAAI;AAAA,WACb,CAAE;AAAA,SACJ;AAAA,MACF;AAGA,MAAA,aAAA,GAAgB,YAAY,aAAA,CAAc,GAAA;AAAA,QACxC,CAAC,GAAA,KAAQ,aAAA,CAAc,GAAG;AAAA,OAC5B;AAAA,IACF,SAAS,KAAA,EAAO;AAEd,MAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,cAAA,EAAiB,OAAO,CAAA,QAAA,CAAA,EAAY,KAAK,CAAA;AAAA,IACzD;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,EACzD;AAEA,EAAA,OAAO,UAAA;AACT;;;AC1IO,SAAS,wBAAwB,EAAA,EAAoC;AAE1E,EAAA,MAAM,QAAA,GAAW,GAAG,IAAA,GAAO,IAAA,CAAK,UAAU,EAAA,CAAG,IAAI,EAAE,MAAA,GAAS,CAAA;AAC5D,EAAA,MAAM,OAAA,GAAU,GAAG,GAAA,GAAM,IAAA,CAAK,UAAU,EAAA,CAAG,GAAG,EAAE,MAAA,GAAS,CAAA;AAIzD,EAAA,MAAM,QAAA,GAAW,GAAA;AAGjB,EAAA,OAAO,IAAA,CAAK,GAAA;AAAA,IACV,WAAW,OAAA,GAAU,QAAA;AAAA,IACrB;AAAA,GACF;AACF;AAKO,SAAS,oBACd,YAAA,EACQ;AAGR,EAAA,MAAM,YAAA,GAAe,GAAA;AACrB,EAAA,MAAM,mBAAmB,YAAA,CAAa,MAAA;AAAA,IACpC,CAAC,GAAA,EAAK,EAAA,KAAO,GAAA,GAAM,wBAAwB,EAAE,CAAA;AAAA,IAC7C;AAAA,GACF;AACA,EAAA,OAAO,YAAA,GAAe,gBAAA;AACxB;AAUO,SAAS,kBACd,YAAA,EAC4B;AAC5B,EAAA,MAAM,UAAsC,EAAC;AAC7C,EAAA,IAAI,eAAyC,EAAC;AAE9C,EAAA,KAAA,MAAW,MAAM,YAAA,EAAc;AAE7B,IAAA,MAAM,WAAA,GAAc,CAAC,GAAG,YAAA,EAAc,EAAE,CAAA;AACxC,IAAA,MAAM,aAAA,GAAgB,oBAAoB,WAAW,CAAA;AAIrD,IAAA,IACE,YAAA,CAAa,MAAA,IAAU,0BAAA,IACvB,aAAA,GAAgB,oBAAA,EAChB;AAEA,MAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,QAAA,OAAA,CAAQ,KAAK,YAAY,CAAA;AACzB,QAAA,YAAA,GAAe,EAAC;AAAA,MAClB;AAAA,IACF;AAIA,IAAA,YAAA,CAAa,KAAK,EAAE,CAAA;AAAA,EACtB;AAGA,EAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,IAAA,OAAA,CAAQ,KAAK,YAAY,CAAA;AAAA,EAC3B;AAEA,EAAA,OAAO,OAAA;AACT;AC3EA,eAAsB,qBACpB,MAAA,EAC+B;AAC/B,EAAA,MAAM;AAAA,IACJ,YAAA;AAAA,IACA,iBAAA;AAAA,IACA,aAAA,GAAgB,qBAAA;AAAA,IAChB,OAAA,GAAU,eAAA;AAAA,IACV;AAAA,GACF,GAAI,MAAA;AAEJ,EAAA,IAAI,iBAAA,CAAkB,WAAW,CAAA,EAAG;AAClC,IAAA,OAAO,EAAC;AAAA,EACV;AAGA,EAAA,IAAI,SAAA,GAAY,CAAA;AAGhB,EAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,GAAA,CAAI,OAAO,IAAA,KAAS;AACrD,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAMC,iCAAA,CAA0B,YAAA,EAAc;AAAA,QAC5D,IAAA;AAAA,QACA,aAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAA,SAAA,EAAA;AACA,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,UAAA,CAAW,SAAA,EAAW,kBAAkB,MAAM,CAAA;AAAA,MAChD;AAEA,MAAA,OAAO,EAAE,MAAM,OAAA,EAAQ;AAAA,IACzB,SAAS,KAAA,EAAO;AAEd,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,YAAA,EAAe,IAAI,CAAA,sBAAA,EACjB,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CACvD,CAAA;AAAA,OACF;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AAGD,EAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA;AAE3C,EAAA,OAAO,QAAA;AACT;AClDO,SAAS,qBAAA,CACd,SACA,OAAA,EACkB;AAClB,EAAA,MAAMC,QAAA,GAAS,IAAIC,kBAAA,EAAW;AAC9B,EAAAC,6BAAA,CAAuBF,QAAA,EAAQ,EAAE,MAAA,EAAQ,OAAA,EAAS,CAAA;AAClD,EAAA,MAAM,gBAAA,GAAmBG,4BAAA,CAAqB,KAAA,EAAOH,QAAM,CAAA;AAC3D,EAAA,MAAM,UAAA,GAAa,IAAII,sBAAA,CAAeJ,QAAM,CAAA;AAE5C,EAAA,OAAO,EAAE,kBAAkB,UAAA,EAAW;AACxC;;;ACAO,IAAM,cAAN,MAAkB;AAAA,EAIvB,YAAY,OAAA,EAA8C;AACxD,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA;AACtB,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,cAAc,MAAA,EAKqC;AACvD,IAAA,OAAO,kBAAA,CAAmB;AAAA,MACxB,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,MAAA,EAGa;AAC9B,IAAA,OAAO,yBAAA,CAA0B;AAAA,MAC/B,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBAAkB,MAAA,EAKK;AAC3B,IAAA,OAAO,iBAAA,CAAkB;AAAA,MACvB,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,mBAAmB,MAAA,EAKM;AAC7B,IAAA,OAAO,0BAAA,CAA2B;AAAA,MAChC,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,wBAAwB,MAAA,EASC;AAC7B,IAAA,OAAO,uBAAA,CAAwB;AAAA,MAC7B,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,OAAA,EAAuB;AACtC,IAAA,OAAO,qBAAA,CAAsB,OAAA,EAAS,IAAA,CAAK,OAAO,CAAA;AAAA,EACpD;AACF","file":"index.js","sourcesContent":["import type { RetryConfig } from \"./types\";\n\n/**\n * EIP-712 domain name for relay session signing\n */\nexport const RELAY_DOMAIN_NAME = \"Net Relay Service\";\n\n/**\n * EIP-712 domain version for relay session signing\n */\nexport const RELAY_DOMAIN_VERSION = \"1\";\n\n/**\n * EIP-712 types for relay session signing\n */\nexport const RELAY_SESSION_TYPES = {\n RelaySession: [\n { name: \"operatorAddress\", type: \"address\" },\n { name: \"secretKeyHash\", type: \"bytes32\" },\n { name: \"expiresAt\", type: \"uint256\" },\n ],\n} as const;\n\n/**\n * Default retry configuration\n */\nexport const DEFAULT_RETRY_CONFIG: Required<RetryConfig> = {\n maxRetries: 3,\n initialDelay: 1000,\n maxDelay: 30000,\n backoffMultiplier: 2,\n};\n\n/**\n * Default number of confirmations to wait for\n */\nexport const DEFAULT_CONFIRMATIONS = 1;\n\n/**\n * Default timeout for waiting for transaction confirmations (milliseconds)\n */\nexport const DEFAULT_TIMEOUT = 60000; // 60 seconds\n\n/**\n * Maximum transactions per batch (matches server limit)\n */\nexport const MAX_TRANSACTIONS_PER_BATCH = 100;\n\n/**\n * Maximum request size in bytes (slightly under 1MB for safety margin)\n */\nexport const MAX_BATCH_SIZE_BYTES = 900 * 1024; // 900KB\n\n/**\n * Maximum size per transaction in bytes\n * Storage transactions can include large data chunks (up to ~200KB per transaction)\n * This cap prevents a single malformed transaction from blocking the entire batch\n */\nexport const MAX_TRANSACTION_SIZE_BYTES = 250 * 1024; // 250KB\n\n","import { keccak256, toBytes } from \"viem\";\nimport type { LocalAccount, Address } from \"viem/accounts\";\nimport {\n RELAY_DOMAIN_NAME,\n RELAY_DOMAIN_VERSION,\n RELAY_SESSION_TYPES,\n} from \"./constants\";\nimport type { CreateSessionResponse, ErrorResponse } from \"./types\";\n\n/**\n * Create a relay session token\n *\n * Signs an EIP-712 message proving ownership of operatorAddress\n * and receives a sessionToken that can be reused for multiple batch requests.\n *\n * @param params - Session creation parameters\n * @returns Session token and expiration timestamp\n * @throws Error if session creation fails\n */\nexport async function createRelaySession(params: {\n apiUrl: string;\n chainId: number;\n operatorAddress: Address;\n secretKey: string;\n account: LocalAccount;\n expiresIn?: number; // seconds, default 3600\n}): Promise<{ sessionToken: string; expiresAt: number }> {\n const { apiUrl, chainId, operatorAddress, secretKey, account, expiresIn } =\n params;\n\n const expiresInSeconds = expiresIn || 3600; // Default 1 hour\n const expiresAt = Math.floor(Date.now() / 1000) + expiresInSeconds;\n const secretKeyHash = keccak256(toBytes(secretKey));\n\n const domain = {\n name: RELAY_DOMAIN_NAME,\n version: RELAY_DOMAIN_VERSION,\n chainId,\n };\n\n const message = {\n operatorAddress,\n secretKeyHash,\n expiresAt: BigInt(expiresAt),\n };\n\n // Sign the typed data using account's signTypedData method\n const signature = await account.signTypedData({\n domain,\n types: RELAY_SESSION_TYPES,\n primaryType: \"RelaySession\",\n message,\n });\n\n // Call session endpoint (send expiresAt - the exact value that was signed)\n const response = await fetch(`${apiUrl}/api/relay/session`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n signature,\n expiresAt, // Send the exact expiresAt that was signed\n }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new Error(\n `Session creation failed: ${response.status} ${\n errorData.error || response.statusText\n }`\n );\n }\n\n const result = (await response.json()) as\n | CreateSessionResponse\n | ErrorResponse;\n if (!result.success || \"error\" in result) {\n throw new Error(\n `Session creation failed: ${\n (\"error\" in result ? result.error : null) || \"Unknown error\"\n }`\n );\n }\n\n if (!result.sessionToken || !result.expiresAt) {\n throw new Error(\n \"Session creation failed: Missing sessionToken or expiresAt in response\"\n );\n }\n\n return {\n sessionToken: result.sessionToken,\n expiresAt: result.expiresAt,\n };\n}\n\n","import type {\n CheckBackendWalletBalanceParams,\n CheckBalanceResult,\n BalanceResponse,\n ErrorResponse,\n} from \"./types\";\n\n/**\n * Check backend wallet balance via relay service\n *\n * This function:\n * 1. Calls /api/relay/balance with operatorAddress and secretKey\n * 2. Returns balance information including sufficientBalance flag\n *\n * @param params - Balance check parameters\n * @returns Result with balance information\n * @throws Error if balance check fails\n */\nexport async function checkBackendWalletBalance(\n params: CheckBackendWalletBalanceParams\n): Promise<CheckBalanceResult> {\n const { apiUrl, chainId, operatorAddress, secretKey } = params;\n\n const response = await fetch(`${apiUrl}/api/relay/balance`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new Error(\n `Balance check endpoint failed: ${response.status} ${JSON.stringify(\n errorData\n )}`\n );\n }\n\n const result = (await response.json()) as BalanceResponse | ErrorResponse;\n if (!result.success || \"error\" in result) {\n throw new Error(\n `Balance check failed: ${(\"error\" in result ? result.error : null) || \"Unknown error\"}`\n );\n }\n\n return {\n backendWalletAddress: result.backendWalletAddress,\n balanceWei: result.balanceWei,\n balanceEth: result.balanceEth,\n sufficientBalance: result.sufficientBalance,\n minRequiredWei: result.minRequiredWei,\n minRequiredEth: result.minRequiredEth,\n };\n}\n\n","import type { Hash } from \"viem\";\nimport type {\n FundBackendWalletParams,\n RelayFundResult,\n FundResponse,\n VerifyFundResponse,\n ErrorResponse,\n} from \"./types\";\n\n/**\n * Extract payment transaction hash from response headers\n */\nfunction extractPaymentTxHash(\n response: Response,\n httpClient: FundBackendWalletParams[\"httpClient\"]\n): string | null {\n try {\n const paymentResponse = httpClient.getPaymentSettleResponse(\n (name: string) => response.headers.get(name)\n );\n return paymentResponse?.transaction || paymentResponse?.txHash || null;\n } catch (error) {\n console.error(\"Failed to extract payment transaction hash:\", error);\n return null;\n }\n}\n\n/**\n * Determine if a verify error is retryable based on HTTP status and error message\n */\nfunction isRetryableVerifyError(\n statusCode: number,\n errorMessage: string\n): boolean {\n // 5xx = always retryable\n if (statusCode >= 500) return true;\n\n // 4xx = check for retryable patterns\n if (statusCode >= 400 && statusCode < 500) {\n const msg = errorMessage.toLowerCase();\n return (\n msg.includes(\"failed to fetch payment transaction\") ||\n msg.includes(\"treasury wallet has insufficient balance\") ||\n msg.includes(\"transferfailed\")\n );\n }\n\n return false;\n}\n\n/**\n * Retry /fund/verify with exponential backoff\n */\nasync function verifyFundWithRetry(\n apiUrl: string,\n paymentTxHash: Hash,\n operatorAddress: string,\n secretKey: string,\n chainId: number\n): Promise<VerifyFundResponse> {\n const maxRetries = 3;\n const initialDelayMs = 2000;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const response = await fetch(`${apiUrl}/api/relay/fund/verify`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n chainId,\n paymentTxHash,\n operatorAddress,\n secretKey,\n }),\n });\n\n const data = (await response.json()) as VerifyFundResponse | ErrorResponse;\n\n if (response.ok && data.success) {\n return data as VerifyFundResponse;\n }\n\n const errorMessage = (data as ErrorResponse).error || \"Unknown error\";\n\n // Don't retry non-retryable errors\n if (!isRetryableVerifyError(response.status, errorMessage)) {\n throw new Error(`Fund verify failed: ${response.status} ${errorMessage}`);\n }\n\n // Last attempt failed\n if (attempt === maxRetries) {\n throw new Error(\n `Fund verify failed after ${maxRetries + 1} attempts: ${errorMessage}`\n );\n }\n\n // Wait before retry (exponential backoff)\n const delayMs = initialDelayMs * Math.pow(2, attempt);\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n throw new Error(\"Verify failed after all retries\");\n}\n\n/**\n * Fund backend wallet via x402 relay service\n *\n * This function:\n * 1. Calls /api/relay/[chainId]/fund with x402 payment (using fetchWithPayment)\n * 2. Extracts paymentTxHash from X-PAYMENT-RESPONSE header\n * 3. Waits for payment confirmation (2 seconds)\n * 4. Calls /api/relay/fund/verify to get backendWalletAddress\n * 5. Returns { paymentTxHash, backendWalletAddress }\n *\n * @param params - Funding parameters\n * @returns Result with paymentTxHash and backendWalletAddress\n * @throws Error if funding fails\n */\nexport async function fundBackendWallet(\n params: FundBackendWalletParams\n): Promise<RelayFundResult> {\n const {\n apiUrl,\n operatorAddress,\n secretKey,\n fetchWithPayment,\n httpClient,\n chainId,\n } = params;\n\n const fundUrl = `${apiUrl}/api/relay/${chainId}/fund`;\n\n console.log(\"💰 Funding backend wallet\", {\n url: fundUrl,\n chainId,\n operatorAddress,\n facilitator:\n chainId === 8453\n ? \"Coinbase CDP (Base Mainnet)\"\n : chainId === 84532\n ? \"x402.org (Base Sepolia)\"\n : \"unknown\",\n });\n\n // Step 1: Call /api/relay/[chainId]/fund (Payment)\n let fundResponse: Response;\n try {\n fundResponse = await fetchWithPayment(fundUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n }),\n });\n } catch (error) {\n console.error(\"❌ Fund request failed\", {\n error: error instanceof Error ? error.message : String(error),\n chainId,\n url: fundUrl,\n });\n throw error;\n }\n\n const fundData = (await fundResponse.json()) as FundResponse | ErrorResponse;\n\n // Handle 402 Payment Required\n if (fundResponse.status === 402) {\n // Check if payment was actually processed despite 402\n if (\"payer\" in fundData && fundData.payer) {\n // Payment appears to have been processed\n } else if (\"success\" in fundData && fundData.success) {\n // Payment appears to have been processed\n } else {\n throw new Error(\n `Fund endpoint returned 402 Payment Required: ${JSON.stringify(\n fundData\n )}`\n );\n }\n } else if (!fundResponse.ok) {\n throw new Error(\n `Fund endpoint failed: ${fundResponse.status} ${JSON.stringify(fundData)}`\n );\n }\n\n // Extract payment transaction hash from response headers\n const paymentTxHash = extractPaymentTxHash(fundResponse, httpClient);\n\n if (!paymentTxHash) {\n throw new Error(\n \"Failed to extract payment transaction hash from payment response headers\"\n );\n }\n\n // Step 2: Wait for payment confirmation\n await new Promise((resolve) => setTimeout(resolve, 2000));\n\n // Step 3: Call /api/relay/fund/verify with retry logic\n const verifyData = await verifyFundWithRetry(\n apiUrl,\n paymentTxHash as Hash,\n operatorAddress,\n secretKey,\n chainId\n );\n\n console.log(\"✓ Payment verified and backend wallet funded\", {\n backendWalletAddress: verifyData.backendWalletAddress,\n });\n\n if (!verifyData.backendWalletAddress) {\n throw new Error(\"Backend wallet address not found in verify response\");\n }\n\n return {\n paymentTxHash: paymentTxHash as Hash,\n backendWalletAddress: verifyData.backendWalletAddress,\n };\n}\n","import type { Hash, Address } from \"viem\";\nimport type {\n SubmitTransactionsViaRelayParams,\n RelaySubmitResult,\n SubmitResponse,\n ErrorResponse,\n} from \"./types\";\n\n/**\n * Submit transactions via relay service\n *\n * Calls /api/relay/submit with transactions and returns result\n * with success/failure tracking by index.\n *\n * @param params - Submission parameters\n * @returns Result with transaction hashes and success/failure tracking\n * @throws Error if submission fails\n */\nexport async function submitTransactionsViaRelay(\n params: SubmitTransactionsViaRelayParams\n): Promise<RelaySubmitResult> {\n const {\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n transactions,\n sessionToken,\n } = params;\n\n const response = await fetch(`${apiUrl}/api/relay/submit`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n transactions: transactions.map((tx) => ({\n ...tx,\n // Only include value if it exists and is > 0\n ...(tx.value !== undefined && tx.value > BigInt(0)\n ? { value: tx.value.toString() }\n : {}),\n })),\n sessionToken,\n }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new Error(\n `Relay submit endpoint failed: ${response.status} ${JSON.stringify(\n errorData\n )}`\n );\n }\n\n const result = (await response.json()) as SubmitResponse | ErrorResponse;\n if (!result.success || \"error\" in result) {\n throw new Error(\n `Relay submit failed: ${\n (\"error\" in result ? result.error : null) || \"Unknown error\"\n }`\n );\n }\n\n return {\n transactionHashes: result.transactionHashes.map((h: string) => h as Hash),\n successfulIndexes: result.successfulIndexes || [],\n failedIndexes: result.failedIndexes || [],\n errors: result.errors || [],\n backendWalletAddress: result.backendWalletAddress as Address,\n appFeeTransactionHash: result.appFeeTransactionHash as Hash,\n };\n}\n\n","import type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport type { Address } from \"viem\";\nimport type {\n RetryFailedTransactionsParams,\n RetryConfig,\n RelaySubmitResult,\n} from \"./types\";\nimport { DEFAULT_RETRY_CONFIG } from \"./constants\";\nimport { submitTransactionsViaRelay } from \"./submit\";\n\n/**\n * Sleep for specified milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Calculate delay for exponential backoff\n */\nfunction calculateDelay(\n attempt: number,\n config: Required<RetryConfig>\n): number {\n const delay =\n config.initialDelay * Math.pow(config.backoffMultiplier, attempt);\n return Math.min(delay, config.maxDelay);\n}\n\n/**\n * Retry failed transactions with exponential backoff\n *\n * This function:\n * 1. Extracts failed transactions by index from RelaySubmitResult\n * 2. Optionally re-checks on-chain before retry (via recheckFunction)\n * 3. Retries with exponential backoff\n * 4. Handles nested retries\n *\n * @param params - Retry parameters\n * @returns Final success/failure status after retries\n */\nexport async function retryFailedTransactions(\n params: RetryFailedTransactionsParams\n): Promise<RelaySubmitResult> {\n const {\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n failedIndexes: initialFailedIndexes,\n originalTransactions,\n backendWalletAddress,\n config = {},\n sessionToken,\n recheckFunction,\n } = params;\n\n const retryConfig: Required<RetryConfig> = {\n ...DEFAULT_RETRY_CONFIG,\n ...config,\n };\n\n let failedIndexes = initialFailedIndexes;\n let attempt = 0;\n let lastResult: RelaySubmitResult | null = null;\n\n while (failedIndexes.length > 0 && attempt < retryConfig.maxRetries) {\n attempt++;\n\n // Re-check on-chain before retry (if recheckFunction provided)\n if (recheckFunction) {\n failedIndexes = await recheckFunction(\n failedIndexes,\n originalTransactions,\n backendWalletAddress\n );\n }\n\n if (failedIndexes.length === 0) {\n // All transactions have succeeded\n break;\n }\n\n // Calculate delay for exponential backoff\n const delay = calculateDelay(attempt - 1, retryConfig);\n if (attempt > 1) {\n // Don't delay on first attempt\n await sleep(delay);\n }\n\n // Extract failed transactions\n const failedTransactions = failedIndexes.map(\n (idx) => originalTransactions[idx]\n );\n\n // Retry failed transactions\n try {\n const retryResult = await submitTransactionsViaRelay({\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n transactions: failedTransactions,\n sessionToken,\n });\n\n // Merge results\n if (lastResult) {\n // Combine transaction hashes\n lastResult.transactionHashes.push(...retryResult.transactionHashes);\n // Combine successful indexes (adjust for original index)\n lastResult.successfulIndexes.push(\n ...retryResult.successfulIndexes.map((idx) => failedIndexes[idx])\n );\n // Update failed indexes\n lastResult.failedIndexes = retryResult.failedIndexes.map(\n (idx) => failedIndexes[idx]\n );\n // Combine errors\n lastResult.errors.push(\n ...retryResult.errors.map((err) => ({\n index: failedIndexes[err.index],\n error: err.error,\n }))\n );\n } else {\n lastResult = {\n ...retryResult,\n successfulIndexes: retryResult.successfulIndexes.map(\n (idx) => failedIndexes[idx]\n ),\n failedIndexes: retryResult.failedIndexes.map(\n (idx) => failedIndexes[idx]\n ),\n errors: retryResult.errors.map((err) => ({\n index: failedIndexes[err.index],\n error: err.error,\n })),\n };\n }\n\n // Update failed indexes for next iteration\n failedIndexes = retryResult.failedIndexes.map(\n (idx) => failedIndexes[idx]\n );\n } catch (error) {\n // Retry failed, keep current failed indexes\n console.error(`Retry attempt ${attempt} failed:`, error);\n }\n }\n\n if (!lastResult) {\n throw new Error(\"Retry failed: No result after retries\");\n }\n\n return lastResult;\n}\n\n","import type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport {\n MAX_TRANSACTIONS_PER_BATCH,\n MAX_BATCH_SIZE_BYTES,\n MAX_TRANSACTION_SIZE_BYTES,\n} from \"./constants\";\n\n/**\n * Estimate the size of a serialized transaction config in bytes\n *\n * Storage transactions can be large due to:\n * - Large args arrays (chunk data)\n * - Hex-encoded data in args\n * - Full ABI included in each transaction (can be 2-3KB)\n *\n * The entire transaction object is serialized to JSON, including the ABI,\n * so we must account for all fields.\n */\nexport function estimateTransactionSize(tx: WriteTransactionConfig): number {\n // Measure actual sizes of serialized fields\n const argsSize = tx.args ? JSON.stringify(tx.args).length : 0;\n const abiSize = tx.abi ? JSON.stringify(tx.abi).length : 0;\n \n // Add overhead for: to (~44 bytes), functionName (~20 bytes), \n // JSON structure/keys (~100 bytes)\n const overhead = 200;\n\n // Cap at MAX_TRANSACTION_SIZE_BYTES to prevent single transaction from exceeding batch limit\n return Math.min(\n argsSize + abiSize + overhead,\n MAX_TRANSACTION_SIZE_BYTES\n );\n}\n\n/**\n * Estimate the total request size for a batch of transactions\n */\nexport function estimateRequestSize(\n transactions: WriteTransactionConfig[]\n): number {\n // Base overhead: operatorAddress (~42 bytes),\n // secretKey (~50-200 bytes), JSON structure (~100 bytes)\n const baseOverhead = 300;\n const transactionsSize = transactions.reduce(\n (sum, tx) => sum + estimateTransactionSize(tx),\n 0\n );\n return baseOverhead + transactionsSize;\n}\n\n/**\n * Batch transactions into groups that respect count and size limits\n *\n * With 100KB per transaction estimate:\n * - Size limit: ~9 transactions per batch (900KB / 100KB)\n * - Count limit: 100 transactions per batch\n * - Size limit is the constraining factor for large transactions\n */\nexport function batchTransactions(\n transactions: WriteTransactionConfig[]\n): WriteTransactionConfig[][] {\n const batches: WriteTransactionConfig[][] = [];\n let currentBatch: WriteTransactionConfig[] = [];\n\n for (const tx of transactions) {\n // Calculate what the batch size would be with this transaction added\n const batchWithTx = [...currentBatch, tx];\n const estimatedSize = estimateRequestSize(batchWithTx);\n\n // Check if adding this transaction would exceed limits\n // Size limit is typically the constraining factor (9 transactions @ 100KB each)\n if (\n currentBatch.length >= MAX_TRANSACTIONS_PER_BATCH ||\n estimatedSize > MAX_BATCH_SIZE_BYTES\n ) {\n // Start a new batch\n if (currentBatch.length > 0) {\n batches.push(currentBatch);\n currentBatch = [];\n }\n }\n\n // If a single transaction exceeds the batch size limit, we still add it\n // (it will be its own batch, and the server will reject it with a clear error)\n currentBatch.push(tx);\n }\n\n // Add the last batch if it has transactions\n if (currentBatch.length > 0) {\n batches.push(currentBatch);\n }\n\n return batches;\n}\n\n","import { waitForTransactionReceipt } from \"viem/actions\";\nimport type { Hash } from \"viem\";\nimport type {\n WaitForConfirmationsParams,\n ConfirmationResult,\n} from \"./types\";\nimport { DEFAULT_CONFIRMATIONS, DEFAULT_TIMEOUT } from \"./constants\";\n\n/**\n * Wait for transaction confirmations\n *\n * Uses waitForTransactionReceipt() from viem/actions to wait for\n * multiple transactions in parallel. Handles timeouts and tracks progress.\n *\n * @param params - Confirmation parameters\n * @returns Array of transaction receipts\n * @throws Error if timeout occurs or transaction fails\n */\nexport async function waitForConfirmations(\n params: WaitForConfirmationsParams\n): Promise<ConfirmationResult[]> {\n const {\n publicClient,\n transactionHashes,\n confirmations = DEFAULT_CONFIRMATIONS,\n timeout = DEFAULT_TIMEOUT,\n onProgress,\n } = params;\n\n if (transactionHashes.length === 0) {\n return [];\n }\n\n const results: ConfirmationResult[] = [];\n let confirmed = 0;\n\n // Wait for all transactions in parallel\n const promises = transactionHashes.map(async (hash) => {\n try {\n const receipt = await waitForTransactionReceipt(publicClient, {\n hash,\n confirmations,\n timeout,\n });\n\n confirmed++;\n if (onProgress) {\n onProgress(confirmed, transactionHashes.length);\n }\n\n return { hash, receipt };\n } catch (error) {\n // Transaction failed or timed out\n throw new Error(\n `Transaction ${hash} failed or timed out: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n });\n\n // Wait for all promises\n const receipts = await Promise.all(promises);\n\n return receipts;\n}\n\n","import { x402Client, wrapFetchWithPayment, x402HTTPClient } from \"@x402/fetch\";\nimport { registerExactEvmScheme } from \"@x402/evm/exact/client\";\nimport type { LocalAccount } from \"viem/accounts\";\nimport type { X402ClientResult } from \"../types\";\n\n/**\n * Create x402 client for relay payments\n *\n * Sets up x402Client with user's account, registers EVM scheme,\n * and returns wrapped fetch function and HTTP client for header extraction.\n *\n * @param account - User's local account (from privateKeyToAccount)\n * @param chainId - Chain ID (optional, for logging purposes)\n * @returns Object with fetchWithPayment and httpClient\n */\nexport function createRelayX402Client(\n account: LocalAccount,\n chainId?: number\n): X402ClientResult {\n const client = new x402Client();\n registerExactEvmScheme(client, { signer: account });\n const fetchWithPayment = wrapFetchWithPayment(fetch, client);\n const httpClient = new x402HTTPClient(client);\n\n return { fetchWithPayment, httpClient };\n}\n\n","import type { LocalAccount, Address } from \"viem/accounts\";\nimport type { PublicClient, Hash } from \"viem\";\nimport type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport { createRelaySession } from \"../session\";\nimport { checkBackendWalletBalance } from \"../balance\";\nimport { fundBackendWallet } from \"../fund\";\nimport { submitTransactionsViaRelay } from \"../submit\";\nimport { retryFailedTransactions } from \"../retry\";\nimport { createRelayX402Client } from \"./x402Client\";\nimport type {\n CheckBalanceResult,\n RelayFundResult,\n RelaySubmitResult,\n RetryFailedTransactionsParams,\n RetryConfig,\n FundBackendWalletParams,\n SubmitTransactionsViaRelayParams,\n} from \"../types\";\n\n/**\n * High-level client for Net Relay Service\n *\n * Provides a convenient class-based API that stores apiUrl and chainId,\n * reducing boilerplate when making multiple relay calls.\n */\nexport class RelayClient {\n private apiUrl: string;\n private chainId: number;\n\n constructor(options: { apiUrl: string; chainId: number }) {\n this.apiUrl = options.apiUrl;\n this.chainId = options.chainId;\n }\n\n /**\n * Create a relay session token\n *\n * @param params - Session creation parameters (apiUrl and chainId are already set)\n * @returns Session token and expiration timestamp\n */\n async createSession(params: {\n operatorAddress: Address;\n secretKey: string;\n account: LocalAccount;\n expiresIn?: number;\n }): Promise<{ sessionToken: string; expiresAt: number }> {\n return createRelaySession({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Check backend wallet balance\n *\n * @param params - Balance check parameters (apiUrl and chainId are already set)\n * @returns Result with balance information\n */\n async checkBalance(params: {\n operatorAddress: Address;\n secretKey: string;\n }): Promise<CheckBalanceResult> {\n return checkBackendWalletBalance({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Fund backend wallet via x402 payment\n *\n * @param params - Funding parameters (apiUrl and chainId are already set)\n * @returns Result with paymentTxHash and backendWalletAddress\n */\n async fundBackendWallet(params: {\n operatorAddress: Address;\n secretKey: string;\n fetchWithPayment: typeof fetch;\n httpClient: FundBackendWalletParams[\"httpClient\"];\n }): Promise<RelayFundResult> {\n return fundBackendWallet({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Submit transactions via relay\n *\n * @param params - Submission parameters (apiUrl and chainId are already set)\n * @returns Result with transaction hashes and success/failure tracking\n */\n async submitTransactions(params: {\n operatorAddress: Address;\n secretKey: string;\n transactions: WriteTransactionConfig[];\n sessionToken: string;\n }): Promise<RelaySubmitResult> {\n return submitTransactionsViaRelay({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Retry failed transactions with exponential backoff\n *\n * @param params - Retry parameters (apiUrl and chainId are already set)\n * @returns Final success/failure status after retries\n */\n async retryFailedTransactions(params: {\n operatorAddress: Address;\n secretKey: string;\n failedIndexes: number[];\n originalTransactions: WriteTransactionConfig[];\n backendWalletAddress: Address;\n config?: RetryConfig;\n sessionToken: string;\n recheckFunction?: RetryFailedTransactionsParams[\"recheckFunction\"];\n }): Promise<RelaySubmitResult> {\n return retryFailedTransactions({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Create x402 client for relay payments\n *\n * @param account - User's local account\n * @returns Object with fetchWithPayment and httpClient\n */\n createX402Client(account: LocalAccount) {\n return createRelayX402Client(account, this.chainId);\n }\n}\n\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/session.ts","../src/balance.ts","../src/fund.ts","../src/submit.ts","../src/retry.ts","../src/batch.ts","../src/confirmations.ts","../src/client/x402Client.ts","../src/client/RelayClient.ts"],"names":["keccak256","toBytes","waitForTransactionReceipt","client","x402Client","registerExactEvmScheme","wrapFetchWithPayment","x402HTTPClient"],"mappings":"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","file":"index.js","sourcesContent":["import type { RetryConfig } from \"./types\";\n\n/**\n * EIP-712 domain name for relay session signing\n */\nexport const RELAY_DOMAIN_NAME = \"Net Relay Service\";\n\n/**\n * EIP-712 domain version for relay session signing\n */\nexport const RELAY_DOMAIN_VERSION = \"1\";\n\n/**\n * EIP-712 types for relay session signing\n */\nexport const RELAY_SESSION_TYPES = {\n RelaySession: [\n { name: \"operatorAddress\", type: \"address\" },\n { name: \"secretKeyHash\", type: \"bytes32\" },\n { name: \"expiresAt\", type: \"uint256\" },\n ],\n} as const;\n\n/**\n * Default retry configuration\n */\nexport const DEFAULT_RETRY_CONFIG: Required<RetryConfig> = {\n maxRetries: 3,\n initialDelay: 1000,\n maxDelay: 30000,\n backoffMultiplier: 2,\n};\n\n/**\n * Default number of confirmations to wait for\n */\nexport const DEFAULT_CONFIRMATIONS = 1;\n\n/**\n * Default timeout for waiting for transaction confirmations (milliseconds)\n */\nexport const DEFAULT_TIMEOUT = 60000; // 60 seconds\n\n/**\n * Maximum transactions per batch (matches server limit)\n */\nexport const MAX_TRANSACTIONS_PER_BATCH = 100;\n\n/**\n * Maximum request size in bytes (slightly under 1MB for safety margin)\n */\nexport const MAX_BATCH_SIZE_BYTES = 900 * 1024; // 900KB\n\n/**\n * Maximum size per transaction in bytes\n * Storage transactions can include large data chunks (up to ~200KB per transaction)\n * This cap prevents a single malformed transaction from blocking the entire batch\n */\nexport const MAX_TRANSACTION_SIZE_BYTES = 250 * 1024; // 250KB\n\n","import { keccak256, toBytes } from \"viem\";\nimport type { LocalAccount, Address } from \"viem/accounts\";\nimport {\n RELAY_DOMAIN_NAME,\n RELAY_DOMAIN_VERSION,\n RELAY_SESSION_TYPES,\n} from \"./constants\";\nimport type { CreateSessionResponse, ErrorResponse } from \"./types\";\n\n/**\n * Create a relay session token\n *\n * Signs an EIP-712 message proving ownership of operatorAddress\n * and receives a sessionToken that can be reused for multiple batch requests.\n *\n * @param params - Session creation parameters\n * @returns Session token and expiration timestamp\n * @throws Error if session creation fails\n */\nexport async function createRelaySession(params: {\n apiUrl: string;\n chainId: number;\n operatorAddress: Address;\n secretKey: string;\n account: LocalAccount;\n expiresIn?: number; // seconds, default 3600\n}): Promise<{ sessionToken: string; expiresAt: number }> {\n const { apiUrl, chainId, operatorAddress, secretKey, account, expiresIn } =\n params;\n\n const expiresInSeconds = expiresIn || 3600; // Default 1 hour\n const expiresAt = Math.floor(Date.now() / 1000) + expiresInSeconds;\n const secretKeyHash = keccak256(toBytes(secretKey));\n\n const domain = {\n name: RELAY_DOMAIN_NAME,\n version: RELAY_DOMAIN_VERSION,\n chainId,\n };\n\n const message = {\n operatorAddress,\n secretKeyHash,\n expiresAt: BigInt(expiresAt),\n };\n\n // Sign the typed data using account's signTypedData method\n const signature = await account.signTypedData({\n domain,\n types: RELAY_SESSION_TYPES,\n primaryType: \"RelaySession\",\n message,\n });\n\n // Call session endpoint (send expiresAt - the exact value that was signed)\n const response = await fetch(`${apiUrl}/api/relay/session`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n signature,\n expiresAt, // Send the exact expiresAt that was signed\n }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new Error(\n `Session creation failed: ${response.status} ${\n errorData.error || response.statusText\n }`\n );\n }\n\n const result = (await response.json()) as\n | CreateSessionResponse\n | ErrorResponse;\n if (!result.success || \"error\" in result) {\n throw new Error(\n `Session creation failed: ${\n (\"error\" in result ? result.error : null) || \"Unknown error\"\n }`\n );\n }\n\n if (!result.sessionToken || !result.expiresAt) {\n throw new Error(\n \"Session creation failed: Missing sessionToken or expiresAt in response\"\n );\n }\n\n return {\n sessionToken: result.sessionToken,\n expiresAt: result.expiresAt,\n };\n}\n\n","import type {\n CheckBackendWalletBalanceParams,\n CheckBalanceResult,\n BalanceResponse,\n ErrorResponse,\n} from \"./types\";\n\n/**\n * Check backend wallet balance via relay service\n *\n * This function:\n * 1. Calls /api/relay/balance with operatorAddress and secretKey\n * 2. Returns balance information including sufficientBalance flag\n *\n * @param params - Balance check parameters\n * @returns Result with balance information\n * @throws Error if balance check fails\n */\nexport async function checkBackendWalletBalance(\n params: CheckBackendWalletBalanceParams\n): Promise<CheckBalanceResult> {\n const { apiUrl, chainId, operatorAddress, secretKey } = params;\n\n const response = await fetch(`${apiUrl}/api/relay/balance`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new Error(\n `Balance check endpoint failed: ${response.status} ${JSON.stringify(\n errorData\n )}`\n );\n }\n\n const result = (await response.json()) as BalanceResponse | ErrorResponse;\n if (!result.success || \"error\" in result) {\n throw new Error(\n `Balance check failed: ${(\"error\" in result ? result.error : null) || \"Unknown error\"}`\n );\n }\n\n return {\n backendWalletAddress: result.backendWalletAddress,\n balanceWei: result.balanceWei,\n balanceEth: result.balanceEth,\n sufficientBalance: result.sufficientBalance,\n minRequiredWei: result.minRequiredWei,\n minRequiredEth: result.minRequiredEth,\n };\n}\n\n","import type { Hash } from \"viem\";\nimport type {\n FundBackendWalletParams,\n RelayFundResult,\n FundResponse,\n VerifyFundResponse,\n ErrorResponse,\n} from \"./types\";\n\n/**\n * Extract payment transaction hash from response headers\n */\nfunction extractPaymentTxHash(\n response: Response,\n httpClient: FundBackendWalletParams[\"httpClient\"]\n): string | null {\n try {\n const paymentResponse = httpClient.getPaymentSettleResponse(\n (name: string) => response.headers.get(name)\n );\n return paymentResponse?.transaction || paymentResponse?.txHash || null;\n } catch (error) {\n console.error(\"Failed to extract payment transaction hash:\", error);\n return null;\n }\n}\n\n/**\n * Determine if a verify error is retryable based on HTTP status and error message\n */\nfunction isRetryableVerifyError(\n statusCode: number,\n errorMessage: string\n): boolean {\n // 5xx = always retryable\n if (statusCode >= 500) return true;\n\n // 4xx = check for retryable patterns\n if (statusCode >= 400 && statusCode < 500) {\n const msg = errorMessage.toLowerCase();\n return (\n msg.includes(\"failed to fetch payment transaction\") ||\n msg.includes(\"treasury wallet has insufficient balance\") ||\n msg.includes(\"transferfailed\")\n );\n }\n\n return false;\n}\n\n/**\n * Retry /fund/verify with exponential backoff\n */\nasync function verifyFundWithRetry(\n apiUrl: string,\n paymentTxHash: Hash,\n operatorAddress: string,\n secretKey: string,\n chainId: number\n): Promise<VerifyFundResponse> {\n const maxRetries = 3;\n const initialDelayMs = 2000;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const response = await fetch(`${apiUrl}/api/relay/fund/verify`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n chainId,\n paymentTxHash,\n operatorAddress,\n secretKey,\n }),\n });\n\n const data = (await response.json()) as VerifyFundResponse | ErrorResponse;\n\n if (response.ok && data.success) {\n return data as VerifyFundResponse;\n }\n\n const errorMessage = (data as ErrorResponse).error || \"Unknown error\";\n\n // Don't retry non-retryable errors\n if (!isRetryableVerifyError(response.status, errorMessage)) {\n throw new Error(`Fund verify failed: ${response.status} ${errorMessage}`);\n }\n\n // Last attempt failed\n if (attempt === maxRetries) {\n throw new Error(\n `Fund verify failed after ${maxRetries + 1} attempts: ${errorMessage}`\n );\n }\n\n // Wait before retry (exponential backoff)\n const delayMs = initialDelayMs * Math.pow(2, attempt);\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n throw new Error(\"Verify failed after all retries\");\n}\n\n/**\n * Fund backend wallet via x402 relay service\n *\n * This function:\n * 1. Calls /api/relay/[chainId]/fund with x402 payment (using fetchWithPayment)\n * 2. Extracts paymentTxHash from X-PAYMENT-RESPONSE header\n * 3. Waits for payment confirmation (2 seconds)\n * 4. Calls /api/relay/fund/verify to get backendWalletAddress\n * 5. Returns { paymentTxHash, backendWalletAddress }\n *\n * @param params - Funding parameters\n * @returns Result with paymentTxHash and backendWalletAddress\n * @throws Error if funding fails\n */\nexport async function fundBackendWallet(\n params: FundBackendWalletParams\n): Promise<RelayFundResult> {\n const {\n apiUrl,\n operatorAddress,\n secretKey,\n fetchWithPayment,\n httpClient,\n chainId,\n amount,\n } = params;\n\n // Build URL with optional amount query param\n let fundUrl = `${apiUrl}/api/relay/${chainId}/fund`;\n if (amount !== undefined && amount > 0) {\n fundUrl += `?amount=${amount}`;\n }\n\n console.log(\"💰 Funding backend wallet\", {\n url: fundUrl,\n chainId,\n operatorAddress,\n amount: amount !== undefined ? `$${amount.toFixed(2)}` : \"default\",\n facilitator:\n chainId === 8453\n ? \"Coinbase CDP (Base Mainnet)\"\n : chainId === 84532\n ? \"x402.org (Base Sepolia)\"\n : \"unknown\",\n });\n\n // Step 1: Call /api/relay/[chainId]/fund (Payment)\n let fundResponse: Response;\n try {\n fundResponse = await fetchWithPayment(fundUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n }),\n });\n } catch (error) {\n console.error(\"❌ Fund request failed\", {\n error: error instanceof Error ? error.message : String(error),\n chainId,\n url: fundUrl,\n });\n throw error;\n }\n\n const fundData = (await fundResponse.json()) as FundResponse | ErrorResponse;\n\n // Handle 402 Payment Required\n if (fundResponse.status === 402) {\n // Check if payment was actually processed despite 402\n if (\"payer\" in fundData && fundData.payer) {\n // Payment appears to have been processed\n } else if (\"success\" in fundData && fundData.success) {\n // Payment appears to have been processed\n } else {\n throw new Error(\n `Fund endpoint returned 402 Payment Required: ${JSON.stringify(\n fundData\n )}`\n );\n }\n } else if (!fundResponse.ok) {\n throw new Error(\n `Fund endpoint failed: ${fundResponse.status} ${JSON.stringify(fundData)}`\n );\n }\n\n // Extract payment transaction hash from response headers\n const paymentTxHash = extractPaymentTxHash(fundResponse, httpClient);\n\n if (!paymentTxHash) {\n throw new Error(\n \"Failed to extract payment transaction hash from payment response headers\"\n );\n }\n\n // Step 2: Wait for payment confirmation\n await new Promise((resolve) => setTimeout(resolve, 2000));\n\n // Step 3: Call /api/relay/fund/verify with retry logic\n const verifyData = await verifyFundWithRetry(\n apiUrl,\n paymentTxHash as Hash,\n operatorAddress,\n secretKey,\n chainId\n );\n\n console.log(\"✓ Payment verified and backend wallet funded\", {\n backendWalletAddress: verifyData.backendWalletAddress,\n });\n\n if (!verifyData.backendWalletAddress) {\n throw new Error(\"Backend wallet address not found in verify response\");\n }\n\n return {\n paymentTxHash: paymentTxHash as Hash,\n backendWalletAddress: verifyData.backendWalletAddress,\n };\n}\n","import type { Hash, Address } from \"viem\";\nimport type {\n SubmitTransactionsViaRelayParams,\n RelaySubmitResult,\n SubmitResponse,\n ErrorResponse,\n} from \"./types\";\n\n/**\n * Submit transactions via relay service\n *\n * Calls /api/relay/submit with transactions and returns result\n * with success/failure tracking by index.\n *\n * @param params - Submission parameters\n * @returns Result with transaction hashes and success/failure tracking\n * @throws Error if submission fails\n */\nexport async function submitTransactionsViaRelay(\n params: SubmitTransactionsViaRelayParams\n): Promise<RelaySubmitResult> {\n const {\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n transactions,\n sessionToken,\n } = params;\n\n const response = await fetch(`${apiUrl}/api/relay/submit`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n transactions: transactions.map((tx) => ({\n ...tx,\n // Only include value if it exists and is > 0\n ...(tx.value !== undefined && tx.value > BigInt(0)\n ? { value: tx.value.toString() }\n : {}),\n })),\n sessionToken,\n }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new Error(\n `Relay submit endpoint failed: ${response.status} ${JSON.stringify(\n errorData\n )}`\n );\n }\n\n const result = (await response.json()) as SubmitResponse | ErrorResponse;\n if (!result.success || \"error\" in result) {\n throw new Error(\n `Relay submit failed: ${\n (\"error\" in result ? result.error : null) || \"Unknown error\"\n }`\n );\n }\n\n return {\n transactionHashes: result.transactionHashes.map((h: string) => h as Hash),\n successfulIndexes: result.successfulIndexes || [],\n failedIndexes: result.failedIndexes || [],\n errors: result.errors || [],\n backendWalletAddress: result.backendWalletAddress as Address,\n appFeeTransactionHash: result.appFeeTransactionHash as Hash,\n };\n}\n\n","import type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport type { Address } from \"viem\";\nimport type {\n RetryFailedTransactionsParams,\n RetryConfig,\n RelaySubmitResult,\n} from \"./types\";\nimport { DEFAULT_RETRY_CONFIG } from \"./constants\";\nimport { submitTransactionsViaRelay } from \"./submit\";\n\n/**\n * Sleep for specified milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Calculate delay for exponential backoff\n */\nfunction calculateDelay(\n attempt: number,\n config: Required<RetryConfig>\n): number {\n const delay =\n config.initialDelay * Math.pow(config.backoffMultiplier, attempt);\n return Math.min(delay, config.maxDelay);\n}\n\n/**\n * Retry failed transactions with exponential backoff\n *\n * This function:\n * 1. Extracts failed transactions by index from RelaySubmitResult\n * 2. Optionally re-checks on-chain before retry (via recheckFunction)\n * 3. Retries with exponential backoff\n * 4. Handles nested retries\n *\n * @param params - Retry parameters\n * @returns Final success/failure status after retries\n */\nexport async function retryFailedTransactions(\n params: RetryFailedTransactionsParams\n): Promise<RelaySubmitResult> {\n const {\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n failedIndexes: initialFailedIndexes,\n originalTransactions,\n backendWalletAddress,\n config = {},\n sessionToken,\n recheckFunction,\n } = params;\n\n const retryConfig: Required<RetryConfig> = {\n ...DEFAULT_RETRY_CONFIG,\n ...config,\n };\n\n let failedIndexes = initialFailedIndexes;\n let attempt = 0;\n let lastResult: RelaySubmitResult | null = null;\n\n while (failedIndexes.length > 0 && attempt < retryConfig.maxRetries) {\n attempt++;\n\n // Re-check on-chain before retry (if recheckFunction provided)\n if (recheckFunction) {\n failedIndexes = await recheckFunction(\n failedIndexes,\n originalTransactions,\n backendWalletAddress\n );\n }\n\n if (failedIndexes.length === 0) {\n // All transactions have succeeded\n break;\n }\n\n // Calculate delay for exponential backoff\n const delay = calculateDelay(attempt - 1, retryConfig);\n if (attempt > 1) {\n // Don't delay on first attempt\n await sleep(delay);\n }\n\n // Extract failed transactions\n const failedTransactions = failedIndexes.map(\n (idx) => originalTransactions[idx]\n );\n\n // Retry failed transactions\n try {\n const retryResult = await submitTransactionsViaRelay({\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n transactions: failedTransactions,\n sessionToken,\n });\n\n // Merge results\n if (lastResult) {\n // Combine transaction hashes\n lastResult.transactionHashes.push(...retryResult.transactionHashes);\n // Combine successful indexes (adjust for original index)\n lastResult.successfulIndexes.push(\n ...retryResult.successfulIndexes.map((idx) => failedIndexes[idx])\n );\n // Update failed indexes\n lastResult.failedIndexes = retryResult.failedIndexes.map(\n (idx) => failedIndexes[idx]\n );\n // Combine errors\n lastResult.errors.push(\n ...retryResult.errors.map((err) => ({\n index: failedIndexes[err.index],\n error: err.error,\n }))\n );\n } else {\n lastResult = {\n ...retryResult,\n successfulIndexes: retryResult.successfulIndexes.map(\n (idx) => failedIndexes[idx]\n ),\n failedIndexes: retryResult.failedIndexes.map(\n (idx) => failedIndexes[idx]\n ),\n errors: retryResult.errors.map((err) => ({\n index: failedIndexes[err.index],\n error: err.error,\n })),\n };\n }\n\n // Update failed indexes for next iteration\n failedIndexes = retryResult.failedIndexes.map(\n (idx) => failedIndexes[idx]\n );\n } catch (error) {\n // Retry failed, keep current failed indexes\n console.error(`Retry attempt ${attempt} failed:`, error);\n }\n }\n\n if (!lastResult) {\n throw new Error(\"Retry failed: No result after retries\");\n }\n\n return lastResult;\n}\n\n","import type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport {\n MAX_TRANSACTIONS_PER_BATCH,\n MAX_BATCH_SIZE_BYTES,\n MAX_TRANSACTION_SIZE_BYTES,\n} from \"./constants\";\n\n/**\n * Estimate the size of a serialized transaction config in bytes\n *\n * Storage transactions can be large due to:\n * - Large args arrays (chunk data)\n * - Hex-encoded data in args\n * - Full ABI included in each transaction (can be 2-3KB)\n *\n * The entire transaction object is serialized to JSON, including the ABI,\n * so we must account for all fields.\n */\nexport function estimateTransactionSize(tx: WriteTransactionConfig): number {\n // Measure actual sizes of serialized fields\n const argsSize = tx.args ? JSON.stringify(tx.args).length : 0;\n const abiSize = tx.abi ? JSON.stringify(tx.abi).length : 0;\n \n // Add overhead for: to (~44 bytes), functionName (~20 bytes), \n // JSON structure/keys (~100 bytes)\n const overhead = 200;\n\n // Cap at MAX_TRANSACTION_SIZE_BYTES to prevent single transaction from exceeding batch limit\n return Math.min(\n argsSize + abiSize + overhead,\n MAX_TRANSACTION_SIZE_BYTES\n );\n}\n\n/**\n * Estimate the total request size for a batch of transactions\n */\nexport function estimateRequestSize(\n transactions: WriteTransactionConfig[]\n): number {\n // Base overhead: operatorAddress (~42 bytes),\n // secretKey (~50-200 bytes), JSON structure (~100 bytes)\n const baseOverhead = 300;\n const transactionsSize = transactions.reduce(\n (sum, tx) => sum + estimateTransactionSize(tx),\n 0\n );\n return baseOverhead + transactionsSize;\n}\n\n/**\n * Batch transactions into groups that respect count and size limits\n *\n * With 100KB per transaction estimate:\n * - Size limit: ~9 transactions per batch (900KB / 100KB)\n * - Count limit: 100 transactions per batch\n * - Size limit is the constraining factor for large transactions\n */\nexport function batchTransactions(\n transactions: WriteTransactionConfig[]\n): WriteTransactionConfig[][] {\n const batches: WriteTransactionConfig[][] = [];\n let currentBatch: WriteTransactionConfig[] = [];\n\n for (const tx of transactions) {\n // Calculate what the batch size would be with this transaction added\n const batchWithTx = [...currentBatch, tx];\n const estimatedSize = estimateRequestSize(batchWithTx);\n\n // Check if adding this transaction would exceed limits\n // Size limit is typically the constraining factor (9 transactions @ 100KB each)\n if (\n currentBatch.length >= MAX_TRANSACTIONS_PER_BATCH ||\n estimatedSize > MAX_BATCH_SIZE_BYTES\n ) {\n // Start a new batch\n if (currentBatch.length > 0) {\n batches.push(currentBatch);\n currentBatch = [];\n }\n }\n\n // If a single transaction exceeds the batch size limit, we still add it\n // (it will be its own batch, and the server will reject it with a clear error)\n currentBatch.push(tx);\n }\n\n // Add the last batch if it has transactions\n if (currentBatch.length > 0) {\n batches.push(currentBatch);\n }\n\n return batches;\n}\n\n","import { waitForTransactionReceipt } from \"viem/actions\";\nimport type { Hash } from \"viem\";\nimport type {\n WaitForConfirmationsParams,\n ConfirmationResult,\n} from \"./types\";\nimport { DEFAULT_CONFIRMATIONS, DEFAULT_TIMEOUT } from \"./constants\";\n\n/**\n * Wait for transaction confirmations\n *\n * Uses waitForTransactionReceipt() from viem/actions to wait for\n * multiple transactions in parallel. Handles timeouts and tracks progress.\n *\n * @param params - Confirmation parameters\n * @returns Array of transaction receipts\n * @throws Error if timeout occurs or transaction fails\n */\nexport async function waitForConfirmations(\n params: WaitForConfirmationsParams\n): Promise<ConfirmationResult[]> {\n const {\n publicClient,\n transactionHashes,\n confirmations = DEFAULT_CONFIRMATIONS,\n timeout = DEFAULT_TIMEOUT,\n onProgress,\n } = params;\n\n if (transactionHashes.length === 0) {\n return [];\n }\n\n const results: ConfirmationResult[] = [];\n let confirmed = 0;\n\n // Wait for all transactions in parallel\n const promises = transactionHashes.map(async (hash) => {\n try {\n const receipt = await waitForTransactionReceipt(publicClient, {\n hash,\n confirmations,\n timeout,\n });\n\n confirmed++;\n if (onProgress) {\n onProgress(confirmed, transactionHashes.length);\n }\n\n return { hash, receipt };\n } catch (error) {\n // Transaction failed or timed out\n throw new Error(\n `Transaction ${hash} failed or timed out: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n });\n\n // Wait for all promises\n const receipts = await Promise.all(promises);\n\n return receipts;\n}\n\n","import { x402Client, wrapFetchWithPayment, x402HTTPClient } from \"@x402/fetch\";\nimport { registerExactEvmScheme } from \"@x402/evm/exact/client\";\nimport type { LocalAccount } from \"viem/accounts\";\nimport type { X402ClientResult } from \"../types\";\n\n/**\n * Create x402 client for relay payments\n *\n * Sets up x402Client with user's account, registers EVM scheme,\n * and returns wrapped fetch function and HTTP client for header extraction.\n *\n * @param account - User's local account (from privateKeyToAccount)\n * @param chainId - Chain ID (optional, for logging purposes)\n * @returns Object with fetchWithPayment and httpClient\n */\nexport function createRelayX402Client(\n account: LocalAccount,\n chainId?: number\n): X402ClientResult {\n const client = new x402Client();\n registerExactEvmScheme(client, { signer: account });\n const fetchWithPayment = wrapFetchWithPayment(fetch, client);\n const httpClient = new x402HTTPClient(client);\n\n return { fetchWithPayment, httpClient };\n}\n\n","import type { LocalAccount, Address } from \"viem/accounts\";\nimport type { PublicClient, Hash } from \"viem\";\nimport type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport { createRelaySession } from \"../session\";\nimport { checkBackendWalletBalance } from \"../balance\";\nimport { fundBackendWallet } from \"../fund\";\nimport { submitTransactionsViaRelay } from \"../submit\";\nimport { retryFailedTransactions } from \"../retry\";\nimport { createRelayX402Client } from \"./x402Client\";\nimport type {\n CheckBalanceResult,\n RelayFundResult,\n RelaySubmitResult,\n RetryFailedTransactionsParams,\n RetryConfig,\n FundBackendWalletParams,\n SubmitTransactionsViaRelayParams,\n} from \"../types\";\n\n/**\n * High-level client for Net Relay Service\n *\n * Provides a convenient class-based API that stores apiUrl and chainId,\n * reducing boilerplate when making multiple relay calls.\n */\nexport class RelayClient {\n private apiUrl: string;\n private chainId: number;\n\n constructor(options: { apiUrl: string; chainId: number }) {\n this.apiUrl = options.apiUrl;\n this.chainId = options.chainId;\n }\n\n /**\n * Create a relay session token\n *\n * @param params - Session creation parameters (apiUrl and chainId are already set)\n * @returns Session token and expiration timestamp\n */\n async createSession(params: {\n operatorAddress: Address;\n secretKey: string;\n account: LocalAccount;\n expiresIn?: number;\n }): Promise<{ sessionToken: string; expiresAt: number }> {\n return createRelaySession({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Check backend wallet balance\n *\n * @param params - Balance check parameters (apiUrl and chainId are already set)\n * @returns Result with balance information\n */\n async checkBalance(params: {\n operatorAddress: Address;\n secretKey: string;\n }): Promise<CheckBalanceResult> {\n return checkBackendWalletBalance({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Fund backend wallet via x402 payment\n *\n * @param params - Funding parameters (apiUrl and chainId are already set)\n * @returns Result with paymentTxHash and backendWalletAddress\n */\n async fundBackendWallet(params: {\n operatorAddress: Address;\n secretKey: string;\n fetchWithPayment: typeof fetch;\n httpClient: FundBackendWalletParams[\"httpClient\"];\n /** Optional custom USDC amount. If not provided, uses default minimum. */\n amount?: number;\n }): Promise<RelayFundResult> {\n return fundBackendWallet({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Submit transactions via relay\n *\n * @param params - Submission parameters (apiUrl and chainId are already set)\n * @returns Result with transaction hashes and success/failure tracking\n */\n async submitTransactions(params: {\n operatorAddress: Address;\n secretKey: string;\n transactions: WriteTransactionConfig[];\n sessionToken: string;\n }): Promise<RelaySubmitResult> {\n return submitTransactionsViaRelay({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Retry failed transactions with exponential backoff\n *\n * @param params - Retry parameters (apiUrl and chainId are already set)\n * @returns Final success/failure status after retries\n */\n async retryFailedTransactions(params: {\n operatorAddress: Address;\n secretKey: string;\n failedIndexes: number[];\n originalTransactions: WriteTransactionConfig[];\n backendWalletAddress: Address;\n config?: RetryConfig;\n sessionToken: string;\n recheckFunction?: RetryFailedTransactionsParams[\"recheckFunction\"];\n }): Promise<RelaySubmitResult> {\n return retryFailedTransactions({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Create x402 client for relay payments\n *\n * @param account - User's local account\n * @returns Object with fetchWithPayment and httpClient\n */\n createX402Client(account: LocalAccount) {\n return createRelayX402Client(account, this.chainId);\n }\n}\n\n"]}
package/dist/index.mjs CHANGED
@@ -183,13 +183,18 @@ async function fundBackendWallet(params) {
183
183
  secretKey,
184
184
  fetchWithPayment,
185
185
  httpClient,
186
- chainId
186
+ chainId,
187
+ amount
187
188
  } = params;
188
- const fundUrl = `${apiUrl}/api/relay/${chainId}/fund`;
189
+ let fundUrl = `${apiUrl}/api/relay/${chainId}/fund`;
190
+ if (amount !== void 0 && amount > 0) {
191
+ fundUrl += `?amount=${amount}`;
192
+ }
189
193
  console.log("\u{1F4B0} Funding backend wallet", {
190
194
  url: fundUrl,
191
195
  chainId,
192
196
  operatorAddress,
197
+ amount: amount !== void 0 ? `$${amount.toFixed(2)}` : "default",
193
198
  facilitator: chainId === 8453 ? "Coinbase CDP (Base Mainnet)" : chainId === 84532 ? "x402.org (Base Sepolia)" : "unknown"
194
199
  });
195
200
  let fundResponse;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/session.ts","../src/balance.ts","../src/fund.ts","../src/submit.ts","../src/retry.ts","../src/batch.ts","../src/confirmations.ts","../src/client/x402Client.ts","../src/client/RelayClient.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { RetryConfig } from \"./types\";\n\n/**\n * EIP-712 domain name for relay session signing\n */\nexport const RELAY_DOMAIN_NAME = \"Net Relay Service\";\n\n/**\n * EIP-712 domain version for relay session signing\n */\nexport const RELAY_DOMAIN_VERSION = \"1\";\n\n/**\n * EIP-712 types for relay session signing\n */\nexport const RELAY_SESSION_TYPES = {\n RelaySession: [\n { name: \"operatorAddress\", type: \"address\" },\n { name: \"secretKeyHash\", type: \"bytes32\" },\n { name: \"expiresAt\", type: \"uint256\" },\n ],\n} as const;\n\n/**\n * Default retry configuration\n */\nexport const DEFAULT_RETRY_CONFIG: Required<RetryConfig> = {\n maxRetries: 3,\n initialDelay: 1000,\n maxDelay: 30000,\n backoffMultiplier: 2,\n};\n\n/**\n * Default number of confirmations to wait for\n */\nexport const DEFAULT_CONFIRMATIONS = 1;\n\n/**\n * Default timeout for waiting for transaction confirmations (milliseconds)\n */\nexport const DEFAULT_TIMEOUT = 60000; // 60 seconds\n\n/**\n * Maximum transactions per batch (matches server limit)\n */\nexport const MAX_TRANSACTIONS_PER_BATCH = 100;\n\n/**\n * Maximum request size in bytes (slightly under 1MB for safety margin)\n */\nexport const MAX_BATCH_SIZE_BYTES = 900 * 1024; // 900KB\n\n/**\n * Maximum size per transaction in bytes\n * Storage transactions can include large data chunks (up to ~200KB per transaction)\n * This cap prevents a single malformed transaction from blocking the entire batch\n */\nexport const MAX_TRANSACTION_SIZE_BYTES = 250 * 1024; // 250KB\n\n","import { keccak256, toBytes } from \"viem\";\nimport type { LocalAccount, Address } from \"viem/accounts\";\nimport {\n RELAY_DOMAIN_NAME,\n RELAY_DOMAIN_VERSION,\n RELAY_SESSION_TYPES,\n} from \"./constants\";\nimport type { CreateSessionResponse, ErrorResponse } from \"./types\";\n\n/**\n * Create a relay session token\n *\n * Signs an EIP-712 message proving ownership of operatorAddress\n * and receives a sessionToken that can be reused for multiple batch requests.\n *\n * @param params - Session creation parameters\n * @returns Session token and expiration timestamp\n * @throws Error if session creation fails\n */\nexport async function createRelaySession(params: {\n apiUrl: string;\n chainId: number;\n operatorAddress: Address;\n secretKey: string;\n account: LocalAccount;\n expiresIn?: number; // seconds, default 3600\n}): Promise<{ sessionToken: string; expiresAt: number }> {\n const { apiUrl, chainId, operatorAddress, secretKey, account, expiresIn } =\n params;\n\n const expiresInSeconds = expiresIn || 3600; // Default 1 hour\n const expiresAt = Math.floor(Date.now() / 1000) + expiresInSeconds;\n const secretKeyHash = keccak256(toBytes(secretKey));\n\n const domain = {\n name: RELAY_DOMAIN_NAME,\n version: RELAY_DOMAIN_VERSION,\n chainId,\n };\n\n const message = {\n operatorAddress,\n secretKeyHash,\n expiresAt: BigInt(expiresAt),\n };\n\n // Sign the typed data using account's signTypedData method\n const signature = await account.signTypedData({\n domain,\n types: RELAY_SESSION_TYPES,\n primaryType: \"RelaySession\",\n message,\n });\n\n // Call session endpoint (send expiresAt - the exact value that was signed)\n const response = await fetch(`${apiUrl}/api/relay/session`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n signature,\n expiresAt, // Send the exact expiresAt that was signed\n }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new Error(\n `Session creation failed: ${response.status} ${\n errorData.error || response.statusText\n }`\n );\n }\n\n const result = (await response.json()) as\n | CreateSessionResponse\n | ErrorResponse;\n if (!result.success || \"error\" in result) {\n throw new Error(\n `Session creation failed: ${\n (\"error\" in result ? result.error : null) || \"Unknown error\"\n }`\n );\n }\n\n if (!result.sessionToken || !result.expiresAt) {\n throw new Error(\n \"Session creation failed: Missing sessionToken or expiresAt in response\"\n );\n }\n\n return {\n sessionToken: result.sessionToken,\n expiresAt: result.expiresAt,\n };\n}\n\n","import type {\n CheckBackendWalletBalanceParams,\n CheckBalanceResult,\n BalanceResponse,\n ErrorResponse,\n} from \"./types\";\n\n/**\n * Check backend wallet balance via relay service\n *\n * This function:\n * 1. Calls /api/relay/balance with operatorAddress and secretKey\n * 2. Returns balance information including sufficientBalance flag\n *\n * @param params - Balance check parameters\n * @returns Result with balance information\n * @throws Error if balance check fails\n */\nexport async function checkBackendWalletBalance(\n params: CheckBackendWalletBalanceParams\n): Promise<CheckBalanceResult> {\n const { apiUrl, chainId, operatorAddress, secretKey } = params;\n\n const response = await fetch(`${apiUrl}/api/relay/balance`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new Error(\n `Balance check endpoint failed: ${response.status} ${JSON.stringify(\n errorData\n )}`\n );\n }\n\n const result = (await response.json()) as BalanceResponse | ErrorResponse;\n if (!result.success || \"error\" in result) {\n throw new Error(\n `Balance check failed: ${(\"error\" in result ? result.error : null) || \"Unknown error\"}`\n );\n }\n\n return {\n backendWalletAddress: result.backendWalletAddress,\n balanceWei: result.balanceWei,\n balanceEth: result.balanceEth,\n sufficientBalance: result.sufficientBalance,\n minRequiredWei: result.minRequiredWei,\n minRequiredEth: result.minRequiredEth,\n };\n}\n\n","import type { Hash } from \"viem\";\nimport type {\n FundBackendWalletParams,\n RelayFundResult,\n FundResponse,\n VerifyFundResponse,\n ErrorResponse,\n} from \"./types\";\n\n/**\n * Extract payment transaction hash from response headers\n */\nfunction extractPaymentTxHash(\n response: Response,\n httpClient: FundBackendWalletParams[\"httpClient\"]\n): string | null {\n try {\n const paymentResponse = httpClient.getPaymentSettleResponse(\n (name: string) => response.headers.get(name)\n );\n return paymentResponse?.transaction || paymentResponse?.txHash || null;\n } catch (error) {\n console.error(\"Failed to extract payment transaction hash:\", error);\n return null;\n }\n}\n\n/**\n * Determine if a verify error is retryable based on HTTP status and error message\n */\nfunction isRetryableVerifyError(\n statusCode: number,\n errorMessage: string\n): boolean {\n // 5xx = always retryable\n if (statusCode >= 500) return true;\n\n // 4xx = check for retryable patterns\n if (statusCode >= 400 && statusCode < 500) {\n const msg = errorMessage.toLowerCase();\n return (\n msg.includes(\"failed to fetch payment transaction\") ||\n msg.includes(\"treasury wallet has insufficient balance\") ||\n msg.includes(\"transferfailed\")\n );\n }\n\n return false;\n}\n\n/**\n * Retry /fund/verify with exponential backoff\n */\nasync function verifyFundWithRetry(\n apiUrl: string,\n paymentTxHash: Hash,\n operatorAddress: string,\n secretKey: string,\n chainId: number\n): Promise<VerifyFundResponse> {\n const maxRetries = 3;\n const initialDelayMs = 2000;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const response = await fetch(`${apiUrl}/api/relay/fund/verify`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n chainId,\n paymentTxHash,\n operatorAddress,\n secretKey,\n }),\n });\n\n const data = (await response.json()) as VerifyFundResponse | ErrorResponse;\n\n if (response.ok && data.success) {\n return data as VerifyFundResponse;\n }\n\n const errorMessage = (data as ErrorResponse).error || \"Unknown error\";\n\n // Don't retry non-retryable errors\n if (!isRetryableVerifyError(response.status, errorMessage)) {\n throw new Error(`Fund verify failed: ${response.status} ${errorMessage}`);\n }\n\n // Last attempt failed\n if (attempt === maxRetries) {\n throw new Error(\n `Fund verify failed after ${maxRetries + 1} attempts: ${errorMessage}`\n );\n }\n\n // Wait before retry (exponential backoff)\n const delayMs = initialDelayMs * Math.pow(2, attempt);\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n throw new Error(\"Verify failed after all retries\");\n}\n\n/**\n * Fund backend wallet via x402 relay service\n *\n * This function:\n * 1. Calls /api/relay/[chainId]/fund with x402 payment (using fetchWithPayment)\n * 2. Extracts paymentTxHash from X-PAYMENT-RESPONSE header\n * 3. Waits for payment confirmation (2 seconds)\n * 4. Calls /api/relay/fund/verify to get backendWalletAddress\n * 5. Returns { paymentTxHash, backendWalletAddress }\n *\n * @param params - Funding parameters\n * @returns Result with paymentTxHash and backendWalletAddress\n * @throws Error if funding fails\n */\nexport async function fundBackendWallet(\n params: FundBackendWalletParams\n): Promise<RelayFundResult> {\n const {\n apiUrl,\n operatorAddress,\n secretKey,\n fetchWithPayment,\n httpClient,\n chainId,\n } = params;\n\n const fundUrl = `${apiUrl}/api/relay/${chainId}/fund`;\n\n console.log(\"💰 Funding backend wallet\", {\n url: fundUrl,\n chainId,\n operatorAddress,\n facilitator:\n chainId === 8453\n ? \"Coinbase CDP (Base Mainnet)\"\n : chainId === 84532\n ? \"x402.org (Base Sepolia)\"\n : \"unknown\",\n });\n\n // Step 1: Call /api/relay/[chainId]/fund (Payment)\n let fundResponse: Response;\n try {\n fundResponse = await fetchWithPayment(fundUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n }),\n });\n } catch (error) {\n console.error(\"❌ Fund request failed\", {\n error: error instanceof Error ? error.message : String(error),\n chainId,\n url: fundUrl,\n });\n throw error;\n }\n\n const fundData = (await fundResponse.json()) as FundResponse | ErrorResponse;\n\n // Handle 402 Payment Required\n if (fundResponse.status === 402) {\n // Check if payment was actually processed despite 402\n if (\"payer\" in fundData && fundData.payer) {\n // Payment appears to have been processed\n } else if (\"success\" in fundData && fundData.success) {\n // Payment appears to have been processed\n } else {\n throw new Error(\n `Fund endpoint returned 402 Payment Required: ${JSON.stringify(\n fundData\n )}`\n );\n }\n } else if (!fundResponse.ok) {\n throw new Error(\n `Fund endpoint failed: ${fundResponse.status} ${JSON.stringify(fundData)}`\n );\n }\n\n // Extract payment transaction hash from response headers\n const paymentTxHash = extractPaymentTxHash(fundResponse, httpClient);\n\n if (!paymentTxHash) {\n throw new Error(\n \"Failed to extract payment transaction hash from payment response headers\"\n );\n }\n\n // Step 2: Wait for payment confirmation\n await new Promise((resolve) => setTimeout(resolve, 2000));\n\n // Step 3: Call /api/relay/fund/verify with retry logic\n const verifyData = await verifyFundWithRetry(\n apiUrl,\n paymentTxHash as Hash,\n operatorAddress,\n secretKey,\n chainId\n );\n\n console.log(\"✓ Payment verified and backend wallet funded\", {\n backendWalletAddress: verifyData.backendWalletAddress,\n });\n\n if (!verifyData.backendWalletAddress) {\n throw new Error(\"Backend wallet address not found in verify response\");\n }\n\n return {\n paymentTxHash: paymentTxHash as Hash,\n backendWalletAddress: verifyData.backendWalletAddress,\n };\n}\n","import type { Hash, Address } from \"viem\";\nimport type {\n SubmitTransactionsViaRelayParams,\n RelaySubmitResult,\n SubmitResponse,\n ErrorResponse,\n} from \"./types\";\n\n/**\n * Submit transactions via relay service\n *\n * Calls /api/relay/submit with transactions and returns result\n * with success/failure tracking by index.\n *\n * @param params - Submission parameters\n * @returns Result with transaction hashes and success/failure tracking\n * @throws Error if submission fails\n */\nexport async function submitTransactionsViaRelay(\n params: SubmitTransactionsViaRelayParams\n): Promise<RelaySubmitResult> {\n const {\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n transactions,\n sessionToken,\n } = params;\n\n const response = await fetch(`${apiUrl}/api/relay/submit`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n transactions: transactions.map((tx) => ({\n ...tx,\n // Only include value if it exists and is > 0\n ...(tx.value !== undefined && tx.value > BigInt(0)\n ? { value: tx.value.toString() }\n : {}),\n })),\n sessionToken,\n }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new Error(\n `Relay submit endpoint failed: ${response.status} ${JSON.stringify(\n errorData\n )}`\n );\n }\n\n const result = (await response.json()) as SubmitResponse | ErrorResponse;\n if (!result.success || \"error\" in result) {\n throw new Error(\n `Relay submit failed: ${\n (\"error\" in result ? result.error : null) || \"Unknown error\"\n }`\n );\n }\n\n return {\n transactionHashes: result.transactionHashes.map((h: string) => h as Hash),\n successfulIndexes: result.successfulIndexes || [],\n failedIndexes: result.failedIndexes || [],\n errors: result.errors || [],\n backendWalletAddress: result.backendWalletAddress as Address,\n appFeeTransactionHash: result.appFeeTransactionHash as Hash,\n };\n}\n\n","import type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport type { Address } from \"viem\";\nimport type {\n RetryFailedTransactionsParams,\n RetryConfig,\n RelaySubmitResult,\n} from \"./types\";\nimport { DEFAULT_RETRY_CONFIG } from \"./constants\";\nimport { submitTransactionsViaRelay } from \"./submit\";\n\n/**\n * Sleep for specified milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Calculate delay for exponential backoff\n */\nfunction calculateDelay(\n attempt: number,\n config: Required<RetryConfig>\n): number {\n const delay =\n config.initialDelay * Math.pow(config.backoffMultiplier, attempt);\n return Math.min(delay, config.maxDelay);\n}\n\n/**\n * Retry failed transactions with exponential backoff\n *\n * This function:\n * 1. Extracts failed transactions by index from RelaySubmitResult\n * 2. Optionally re-checks on-chain before retry (via recheckFunction)\n * 3. Retries with exponential backoff\n * 4. Handles nested retries\n *\n * @param params - Retry parameters\n * @returns Final success/failure status after retries\n */\nexport async function retryFailedTransactions(\n params: RetryFailedTransactionsParams\n): Promise<RelaySubmitResult> {\n const {\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n failedIndexes: initialFailedIndexes,\n originalTransactions,\n backendWalletAddress,\n config = {},\n sessionToken,\n recheckFunction,\n } = params;\n\n const retryConfig: Required<RetryConfig> = {\n ...DEFAULT_RETRY_CONFIG,\n ...config,\n };\n\n let failedIndexes = initialFailedIndexes;\n let attempt = 0;\n let lastResult: RelaySubmitResult | null = null;\n\n while (failedIndexes.length > 0 && attempt < retryConfig.maxRetries) {\n attempt++;\n\n // Re-check on-chain before retry (if recheckFunction provided)\n if (recheckFunction) {\n failedIndexes = await recheckFunction(\n failedIndexes,\n originalTransactions,\n backendWalletAddress\n );\n }\n\n if (failedIndexes.length === 0) {\n // All transactions have succeeded\n break;\n }\n\n // Calculate delay for exponential backoff\n const delay = calculateDelay(attempt - 1, retryConfig);\n if (attempt > 1) {\n // Don't delay on first attempt\n await sleep(delay);\n }\n\n // Extract failed transactions\n const failedTransactions = failedIndexes.map(\n (idx) => originalTransactions[idx]\n );\n\n // Retry failed transactions\n try {\n const retryResult = await submitTransactionsViaRelay({\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n transactions: failedTransactions,\n sessionToken,\n });\n\n // Merge results\n if (lastResult) {\n // Combine transaction hashes\n lastResult.transactionHashes.push(...retryResult.transactionHashes);\n // Combine successful indexes (adjust for original index)\n lastResult.successfulIndexes.push(\n ...retryResult.successfulIndexes.map((idx) => failedIndexes[idx])\n );\n // Update failed indexes\n lastResult.failedIndexes = retryResult.failedIndexes.map(\n (idx) => failedIndexes[idx]\n );\n // Combine errors\n lastResult.errors.push(\n ...retryResult.errors.map((err) => ({\n index: failedIndexes[err.index],\n error: err.error,\n }))\n );\n } else {\n lastResult = {\n ...retryResult,\n successfulIndexes: retryResult.successfulIndexes.map(\n (idx) => failedIndexes[idx]\n ),\n failedIndexes: retryResult.failedIndexes.map(\n (idx) => failedIndexes[idx]\n ),\n errors: retryResult.errors.map((err) => ({\n index: failedIndexes[err.index],\n error: err.error,\n })),\n };\n }\n\n // Update failed indexes for next iteration\n failedIndexes = retryResult.failedIndexes.map(\n (idx) => failedIndexes[idx]\n );\n } catch (error) {\n // Retry failed, keep current failed indexes\n console.error(`Retry attempt ${attempt} failed:`, error);\n }\n }\n\n if (!lastResult) {\n throw new Error(\"Retry failed: No result after retries\");\n }\n\n return lastResult;\n}\n\n","import type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport {\n MAX_TRANSACTIONS_PER_BATCH,\n MAX_BATCH_SIZE_BYTES,\n MAX_TRANSACTION_SIZE_BYTES,\n} from \"./constants\";\n\n/**\n * Estimate the size of a serialized transaction config in bytes\n *\n * Storage transactions can be large due to:\n * - Large args arrays (chunk data)\n * - Hex-encoded data in args\n * - Full ABI included in each transaction (can be 2-3KB)\n *\n * The entire transaction object is serialized to JSON, including the ABI,\n * so we must account for all fields.\n */\nexport function estimateTransactionSize(tx: WriteTransactionConfig): number {\n // Measure actual sizes of serialized fields\n const argsSize = tx.args ? JSON.stringify(tx.args).length : 0;\n const abiSize = tx.abi ? JSON.stringify(tx.abi).length : 0;\n \n // Add overhead for: to (~44 bytes), functionName (~20 bytes), \n // JSON structure/keys (~100 bytes)\n const overhead = 200;\n\n // Cap at MAX_TRANSACTION_SIZE_BYTES to prevent single transaction from exceeding batch limit\n return Math.min(\n argsSize + abiSize + overhead,\n MAX_TRANSACTION_SIZE_BYTES\n );\n}\n\n/**\n * Estimate the total request size for a batch of transactions\n */\nexport function estimateRequestSize(\n transactions: WriteTransactionConfig[]\n): number {\n // Base overhead: operatorAddress (~42 bytes),\n // secretKey (~50-200 bytes), JSON structure (~100 bytes)\n const baseOverhead = 300;\n const transactionsSize = transactions.reduce(\n (sum, tx) => sum + estimateTransactionSize(tx),\n 0\n );\n return baseOverhead + transactionsSize;\n}\n\n/**\n * Batch transactions into groups that respect count and size limits\n *\n * With 100KB per transaction estimate:\n * - Size limit: ~9 transactions per batch (900KB / 100KB)\n * - Count limit: 100 transactions per batch\n * - Size limit is the constraining factor for large transactions\n */\nexport function batchTransactions(\n transactions: WriteTransactionConfig[]\n): WriteTransactionConfig[][] {\n const batches: WriteTransactionConfig[][] = [];\n let currentBatch: WriteTransactionConfig[] = [];\n\n for (const tx of transactions) {\n // Calculate what the batch size would be with this transaction added\n const batchWithTx = [...currentBatch, tx];\n const estimatedSize = estimateRequestSize(batchWithTx);\n\n // Check if adding this transaction would exceed limits\n // Size limit is typically the constraining factor (9 transactions @ 100KB each)\n if (\n currentBatch.length >= MAX_TRANSACTIONS_PER_BATCH ||\n estimatedSize > MAX_BATCH_SIZE_BYTES\n ) {\n // Start a new batch\n if (currentBatch.length > 0) {\n batches.push(currentBatch);\n currentBatch = [];\n }\n }\n\n // If a single transaction exceeds the batch size limit, we still add it\n // (it will be its own batch, and the server will reject it with a clear error)\n currentBatch.push(tx);\n }\n\n // Add the last batch if it has transactions\n if (currentBatch.length > 0) {\n batches.push(currentBatch);\n }\n\n return batches;\n}\n\n","import { waitForTransactionReceipt } from \"viem/actions\";\nimport type { Hash } from \"viem\";\nimport type {\n WaitForConfirmationsParams,\n ConfirmationResult,\n} from \"./types\";\nimport { DEFAULT_CONFIRMATIONS, DEFAULT_TIMEOUT } from \"./constants\";\n\n/**\n * Wait for transaction confirmations\n *\n * Uses waitForTransactionReceipt() from viem/actions to wait for\n * multiple transactions in parallel. Handles timeouts and tracks progress.\n *\n * @param params - Confirmation parameters\n * @returns Array of transaction receipts\n * @throws Error if timeout occurs or transaction fails\n */\nexport async function waitForConfirmations(\n params: WaitForConfirmationsParams\n): Promise<ConfirmationResult[]> {\n const {\n publicClient,\n transactionHashes,\n confirmations = DEFAULT_CONFIRMATIONS,\n timeout = DEFAULT_TIMEOUT,\n onProgress,\n } = params;\n\n if (transactionHashes.length === 0) {\n return [];\n }\n\n const results: ConfirmationResult[] = [];\n let confirmed = 0;\n\n // Wait for all transactions in parallel\n const promises = transactionHashes.map(async (hash) => {\n try {\n const receipt = await waitForTransactionReceipt(publicClient, {\n hash,\n confirmations,\n timeout,\n });\n\n confirmed++;\n if (onProgress) {\n onProgress(confirmed, transactionHashes.length);\n }\n\n return { hash, receipt };\n } catch (error) {\n // Transaction failed or timed out\n throw new Error(\n `Transaction ${hash} failed or timed out: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n });\n\n // Wait for all promises\n const receipts = await Promise.all(promises);\n\n return receipts;\n}\n\n","import { x402Client, wrapFetchWithPayment, x402HTTPClient } from \"@x402/fetch\";\nimport { registerExactEvmScheme } from \"@x402/evm/exact/client\";\nimport type { LocalAccount } from \"viem/accounts\";\nimport type { X402ClientResult } from \"../types\";\n\n/**\n * Create x402 client for relay payments\n *\n * Sets up x402Client with user's account, registers EVM scheme,\n * and returns wrapped fetch function and HTTP client for header extraction.\n *\n * @param account - User's local account (from privateKeyToAccount)\n * @param chainId - Chain ID (optional, for logging purposes)\n * @returns Object with fetchWithPayment and httpClient\n */\nexport function createRelayX402Client(\n account: LocalAccount,\n chainId?: number\n): X402ClientResult {\n const client = new x402Client();\n registerExactEvmScheme(client, { signer: account });\n const fetchWithPayment = wrapFetchWithPayment(fetch, client);\n const httpClient = new x402HTTPClient(client);\n\n return { fetchWithPayment, httpClient };\n}\n\n","import type { LocalAccount, Address } from \"viem/accounts\";\nimport type { PublicClient, Hash } from \"viem\";\nimport type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport { createRelaySession } from \"../session\";\nimport { checkBackendWalletBalance } from \"../balance\";\nimport { fundBackendWallet } from \"../fund\";\nimport { submitTransactionsViaRelay } from \"../submit\";\nimport { retryFailedTransactions } from \"../retry\";\nimport { createRelayX402Client } from \"./x402Client\";\nimport type {\n CheckBalanceResult,\n RelayFundResult,\n RelaySubmitResult,\n RetryFailedTransactionsParams,\n RetryConfig,\n FundBackendWalletParams,\n SubmitTransactionsViaRelayParams,\n} from \"../types\";\n\n/**\n * High-level client for Net Relay Service\n *\n * Provides a convenient class-based API that stores apiUrl and chainId,\n * reducing boilerplate when making multiple relay calls.\n */\nexport class RelayClient {\n private apiUrl: string;\n private chainId: number;\n\n constructor(options: { apiUrl: string; chainId: number }) {\n this.apiUrl = options.apiUrl;\n this.chainId = options.chainId;\n }\n\n /**\n * Create a relay session token\n *\n * @param params - Session creation parameters (apiUrl and chainId are already set)\n * @returns Session token and expiration timestamp\n */\n async createSession(params: {\n operatorAddress: Address;\n secretKey: string;\n account: LocalAccount;\n expiresIn?: number;\n }): Promise<{ sessionToken: string; expiresAt: number }> {\n return createRelaySession({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Check backend wallet balance\n *\n * @param params - Balance check parameters (apiUrl and chainId are already set)\n * @returns Result with balance information\n */\n async checkBalance(params: {\n operatorAddress: Address;\n secretKey: string;\n }): Promise<CheckBalanceResult> {\n return checkBackendWalletBalance({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Fund backend wallet via x402 payment\n *\n * @param params - Funding parameters (apiUrl and chainId are already set)\n * @returns Result with paymentTxHash and backendWalletAddress\n */\n async fundBackendWallet(params: {\n operatorAddress: Address;\n secretKey: string;\n fetchWithPayment: typeof fetch;\n httpClient: FundBackendWalletParams[\"httpClient\"];\n }): Promise<RelayFundResult> {\n return fundBackendWallet({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Submit transactions via relay\n *\n * @param params - Submission parameters (apiUrl and chainId are already set)\n * @returns Result with transaction hashes and success/failure tracking\n */\n async submitTransactions(params: {\n operatorAddress: Address;\n secretKey: string;\n transactions: WriteTransactionConfig[];\n sessionToken: string;\n }): Promise<RelaySubmitResult> {\n return submitTransactionsViaRelay({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Retry failed transactions with exponential backoff\n *\n * @param params - Retry parameters (apiUrl and chainId are already set)\n * @returns Final success/failure status after retries\n */\n async retryFailedTransactions(params: {\n operatorAddress: Address;\n secretKey: string;\n failedIndexes: number[];\n originalTransactions: WriteTransactionConfig[];\n backendWalletAddress: Address;\n config?: RetryConfig;\n sessionToken: string;\n recheckFunction?: RetryFailedTransactionsParams[\"recheckFunction\"];\n }): Promise<RelaySubmitResult> {\n return retryFailedTransactions({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Create x402 client for relay payments\n *\n * @param account - User's local account\n * @returns Object with fetchWithPayment and httpClient\n */\n createX402Client(account: LocalAccount) {\n return createRelayX402Client(account, this.chainId);\n }\n}\n\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/session.ts","../src/balance.ts","../src/fund.ts","../src/submit.ts","../src/retry.ts","../src/batch.ts","../src/confirmations.ts","../src/client/x402Client.ts","../src/client/RelayClient.ts"],"names":[],"mappings":";;;;;;;;AAKO,IAAM,iBAAA,GAAoB;AAK1B,IAAM,oBAAA,GAAuB;AAK7B,IAAM,mBAAA,GAAsB;AAAA,EACjC,YAAA,EAAc;AAAA,IACZ,EAAE,IAAA,EAAM,iBAAA,EAAmB,IAAA,EAAM,SAAA,EAAU;AAAA,IAC3C,EAAE,IAAA,EAAM,eAAA,EAAiB,IAAA,EAAM,SAAA,EAAU;AAAA,IACzC,EAAE,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,SAAA;AAAU;AAEzC;AAKO,IAAM,oBAAA,GAA8C;AAAA,EACzD,UAAA,EAAY,CAAA;AAAA,EACZ,YAAA,EAAc,GAAA;AAAA,EACd,QAAA,EAAU,GAAA;AAAA,EACV,iBAAA,EAAmB;AACrB;AAKO,IAAM,qBAAA,GAAwB;AAK9B,IAAM,eAAA,GAAkB;AAKxB,IAAM,0BAAA,GAA6B;AAKnC,IAAM,uBAAuB,GAAA,GAAM;AAOnC,IAAM,6BAA6B,GAAA,GAAM;;;ACvChD,eAAsB,mBAAmB,MAAA,EAOgB;AACvD,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAS,iBAAiB,SAAA,EAAW,OAAA,EAAS,WAAU,GACtE,MAAA;AAEF,EAAA,MAAM,mBAAmB,SAAA,IAAa,IAAA;AACtC,EAAA,MAAM,YAAY,IAAA,CAAK,KAAA,CAAM,KAAK,GAAA,EAAI,GAAI,GAAI,CAAA,GAAI,gBAAA;AAClD,EAAA,MAAM,aAAA,GAAgB,SAAA,CAAU,OAAA,CAAQ,SAAS,CAAC,CAAA;AAElD,EAAA,MAAM,MAAA,GAAS;AAAA,IACb,IAAA,EAAM,iBAAA;AAAA,IACN,OAAA,EAAS,oBAAA;AAAA,IACT;AAAA,GACF;AAEA,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,eAAA;AAAA,IACA,aAAA;AAAA,IACA,SAAA,EAAW,OAAO,SAAS;AAAA,GAC7B;AAGA,EAAA,MAAM,SAAA,GAAY,MAAM,OAAA,CAAQ,aAAA,CAAc;AAAA,IAC5C,MAAA;AAAA,IACA,KAAA,EAAO,mBAAA;AAAA,IACP,WAAA,EAAa,cAAA;AAAA,IACb;AAAA,GACD,CAAA;AAGD,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA,kBAAA,CAAA,EAAsB;AAAA,IAC1D,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB;AAAA,KAClB;AAAA,IACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,MACnB,OAAA;AAAA,MACA,eAAA;AAAA,MACA,SAAA;AAAA,MACA,SAAA;AAAA,MACA;AAAA;AAAA,KACD;AAAA,GACF,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,SAAA,GAAa,MAAM,QAAA,CAAS,IAAA,EAAK;AACvC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,4BAA4B,QAAA,CAAS,MAAM,IACzC,SAAA,CAAU,KAAA,IAAS,SAAS,UAC9B,CAAA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAU,MAAM,QAAA,CAAS,IAAA,EAAK;AAGpC,EAAA,IAAI,CAAC,MAAA,CAAO,OAAA,IAAW,OAAA,IAAW,MAAA,EAAQ;AACxC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,6BACG,OAAA,IAAW,MAAA,GAAS,MAAA,CAAO,KAAA,GAAQ,SAAS,eAC/C,CAAA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,MAAA,CAAO,YAAA,IAAgB,CAAC,OAAO,SAAA,EAAW;AAC7C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,cAAc,MAAA,CAAO,YAAA;AAAA,IACrB,WAAW,MAAA,CAAO;AAAA,GACpB;AACF;;;ACjFA,eAAsB,0BACpB,MAAA,EAC6B;AAC7B,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAS,eAAA,EAAiB,WAAU,GAAI,MAAA;AAExD,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA,kBAAA,CAAA,EAAsB;AAAA,IAC1D,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB;AAAA,KAClB;AAAA,IACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,MACnB,OAAA;AAAA,MACA,eAAA;AAAA,MACA;AAAA,KACD;AAAA,GACF,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,SAAA,GAAa,MAAM,QAAA,CAAS,IAAA,EAAK;AACvC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,+BAAA,EAAkC,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA;AAAA,QACxD;AAAA,OACD,CAAA;AAAA,KACH;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAU,MAAM,QAAA,CAAS,IAAA,EAAK;AACpC,EAAA,IAAI,CAAC,MAAA,CAAO,OAAA,IAAW,OAAA,IAAW,MAAA,EAAQ;AACxC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,0BAA0B,OAAA,IAAW,MAAA,GAAS,MAAA,CAAO,KAAA,GAAQ,SAAS,eAAe,CAAA;AAAA,KACvF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,sBAAsB,MAAA,CAAO,oBAAA;AAAA,IAC7B,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,mBAAmB,MAAA,CAAO,iBAAA;AAAA,IAC1B,gBAAgB,MAAA,CAAO,cAAA;AAAA,IACvB,gBAAgB,MAAA,CAAO;AAAA,GACzB;AACF;;;AC/CA,SAAS,oBAAA,CACP,UACA,UAAA,EACe;AACf,EAAA,IAAI;AACF,IAAA,MAAM,kBAAkB,UAAA,CAAW,wBAAA;AAAA,MACjC,CAAC,IAAA,KAAiB,QAAA,CAAS,OAAA,CAAQ,IAAI,IAAI;AAAA,KAC7C;AACA,IAAA,OAAO,eAAA,EAAiB,WAAA,IAAe,eAAA,EAAiB,MAAA,IAAU,IAAA;AAAA,EACpE,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,+CAA+C,KAAK,CAAA;AAClE,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAKA,SAAS,sBAAA,CACP,YACA,YAAA,EACS;AAET,EAAA,IAAI,UAAA,IAAc,KAAK,OAAO,IAAA;AAG9B,EAAA,IAAI,UAAA,IAAc,GAAA,IAAO,UAAA,GAAa,GAAA,EAAK;AACzC,IAAA,MAAM,GAAA,GAAM,aAAa,WAAA,EAAY;AACrC,IAAA,OACE,GAAA,CAAI,QAAA,CAAS,qCAAqC,CAAA,IAClD,GAAA,CAAI,SAAS,0CAA0C,CAAA,IACvD,GAAA,CAAI,QAAA,CAAS,gBAAgB,CAAA;AAAA,EAEjC;AAEA,EAAA,OAAO,KAAA;AACT;AAKA,eAAe,mBAAA,CACb,MAAA,EACA,aAAA,EACA,eAAA,EACA,WACA,OAAA,EAC6B;AAC7B,EAAA,MAAM,UAAA,GAAa,CAAA;AACnB,EAAA,MAAM,cAAA,GAAiB,GAAA;AAEvB,EAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,UAAA,EAAY,OAAA,EAAA,EAAW;AACtD,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA,sBAAA,CAAA,EAA0B;AAAA,MAC9D,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,OAAA;AAAA,QACA,aAAA;AAAA,QACA,eAAA;AAAA,QACA;AAAA,OACD;AAAA,KACF,CAAA;AAED,IAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAElC,IAAA,IAAI,QAAA,CAAS,EAAA,IAAM,IAAA,CAAK,OAAA,EAAS;AAC/B,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,YAAA,GAAgB,KAAuB,KAAA,IAAS,eAAA;AAGtD,IAAA,IAAI,CAAC,sBAAA,CAAuB,QAAA,CAAS,MAAA,EAAQ,YAAY,CAAA,EAAG;AAC1D,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,SAAS,MAAM,CAAA,CAAA,EAAI,YAAY,CAAA,CAAE,CAAA;AAAA,IAC1E;AAGA,IAAA,IAAI,YAAY,UAAA,EAAY;AAC1B,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,yBAAA,EAA4B,UAAA,GAAa,CAAC,CAAA,WAAA,EAAc,YAAY,CAAA;AAAA,OACtE;AAAA,IACF;AAGA,IAAA,MAAM,OAAA,GAAU,cAAA,GAAiB,IAAA,CAAK,GAAA,CAAI,GAAG,OAAO,CAAA;AACpD,IAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA,EAC7D;AAEA,EAAA,MAAM,IAAI,MAAM,iCAAiC,CAAA;AACnD;AAgBA,eAAsB,kBACpB,MAAA,EAC0B;AAC1B,EAAA,MAAM;AAAA,IACJ,MAAA;AAAA,IACA,eAAA;AAAA,IACA,SAAA;AAAA,IACA,gBAAA;AAAA,IACA,UAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF,GAAI,MAAA;AAGJ,EAAA,IAAI,OAAA,GAAU,CAAA,EAAG,MAAM,CAAA,WAAA,EAAc,OAAO,CAAA,KAAA,CAAA;AAC5C,EAAA,IAAI,MAAA,KAAW,MAAA,IAAa,MAAA,GAAS,CAAA,EAAG;AACtC,IAAA,OAAA,IAAW,WAAW,MAAM,CAAA,CAAA;AAAA,EAC9B;AAEA,EAAA,OAAA,CAAQ,IAAI,kCAAA,EAA6B;AAAA,IACvC,GAAA,EAAK,OAAA;AAAA,IACL,OAAA;AAAA,IACA,eAAA;AAAA,IACA,MAAA,EAAQ,WAAW,MAAA,GAAY,CAAA,CAAA,EAAI,OAAO,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,GAAK,SAAA;AAAA,IACzD,aACE,OAAA,KAAY,IAAA,GACR,6BAAA,GACA,OAAA,KAAY,QACZ,yBAAA,GACA;AAAA,GACP,CAAA;AAGD,EAAA,IAAI,YAAA;AACJ,EAAA,IAAI;AACF,IAAA,YAAA,GAAe,MAAM,iBAAiB,OAAA,EAAS;AAAA,MAC7C,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB;AAAA,OAClB;AAAA,MACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,OAAA;AAAA,QACA,eAAA;AAAA,QACA;AAAA,OACD;AAAA,KACF,CAAA;AAAA,EACH,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,MAAM,4BAAA,EAAyB;AAAA,MACrC,OAAO,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAAA,MAC5D,OAAA;AAAA,MACA,GAAA,EAAK;AAAA,KACN,CAAA;AACD,IAAA,MAAM,KAAA;AAAA,EACR;AAEA,EAAA,MAAM,QAAA,GAAY,MAAM,YAAA,CAAa,IAAA,EAAK;AAG1C,EAAA,IAAI,YAAA,CAAa,WAAW,GAAA,EAAK;AAE/B,IAAA,IAAI,OAAA,IAAW,QAAA,IAAY,QAAA,CAAS,KAAA,EAAO,CAE3C,MAAA,IAAW,SAAA,IAAa,QAAA,IAAY,QAAA,CAAS,OAAA,EAAS,CAEtD,MAAO;AACL,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,gDAAgD,IAAA,CAAK,SAAA;AAAA,UACnD;AAAA,SACD,CAAA;AAAA,OACH;AAAA,IACF;AAAA,EACF,CAAA,MAAA,IAAW,CAAC,YAAA,CAAa,EAAA,EAAI;AAC3B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,yBAAyB,YAAA,CAAa,MAAM,IAAI,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAC,CAAA;AAAA,KAC1E;AAAA,EACF;AAGA,EAAA,MAAM,aAAA,GAAgB,oBAAA,CAAqB,YAAA,EAAc,UAAU,CAAA;AAEnE,EAAA,IAAI,CAAC,aAAA,EAAe;AAClB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAGA,EAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,GAAI,CAAC,CAAA;AAGxD,EAAA,MAAM,aAAa,MAAM,mBAAA;AAAA,IACvB,MAAA;AAAA,IACA,aAAA;AAAA,IACA,eAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAA,CAAQ,IAAI,mDAAA,EAAgD;AAAA,IAC1D,sBAAsB,UAAA,CAAW;AAAA,GAClC,CAAA;AAED,EAAA,IAAI,CAAC,WAAW,oBAAA,EAAsB;AACpC,IAAA,MAAM,IAAI,MAAM,qDAAqD,CAAA;AAAA,EACvE;AAEA,EAAA,OAAO;AAAA,IACL,aAAA;AAAA,IACA,sBAAsB,UAAA,CAAW;AAAA,GACnC;AACF;;;ACjNA,eAAsB,2BACpB,MAAA,EAC4B;AAC5B,EAAA,MAAM;AAAA,IACJ,MAAA;AAAA,IACA,OAAA;AAAA,IACA,eAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACF,GAAI,MAAA;AAEJ,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA,iBAAA,CAAA,EAAqB;AAAA,IACzD,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB;AAAA,KAClB;AAAA,IACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,MACnB,OAAA;AAAA,MACA,eAAA;AAAA,MACA,SAAA;AAAA,MACA,YAAA,EAAc,YAAA,CAAa,GAAA,CAAI,CAAC,EAAA,MAAQ;AAAA,QACtC,GAAG,EAAA;AAAA;AAAA,QAEH,GAAI,EAAA,CAAG,KAAA,KAAU,MAAA,IAAa,EAAA,CAAG,QAAQ,MAAA,CAAO,CAAC,CAAA,GAC7C,EAAE,OAAO,EAAA,CAAG,KAAA,CAAM,QAAA,EAAS,KAC3B;AAAC,OACP,CAAE,CAAA;AAAA,MACF;AAAA,KACD;AAAA,GACF,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,SAAA,GAAa,MAAM,QAAA,CAAS,IAAA,EAAK;AACvC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,8BAAA,EAAiC,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA;AAAA,QACvD;AAAA,OACD,CAAA;AAAA,KACH;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAU,MAAM,QAAA,CAAS,IAAA,EAAK;AACpC,EAAA,IAAI,CAAC,MAAA,CAAO,OAAA,IAAW,OAAA,IAAW,MAAA,EAAQ;AACxC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,yBACG,OAAA,IAAW,MAAA,GAAS,MAAA,CAAO,KAAA,GAAQ,SAAS,eAC/C,CAAA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,mBAAmB,MAAA,CAAO,iBAAA,CAAkB,GAAA,CAAI,CAAC,MAAc,CAAS,CAAA;AAAA,IACxE,iBAAA,EAAmB,MAAA,CAAO,iBAAA,IAAqB,EAAC;AAAA,IAChD,aAAA,EAAe,MAAA,CAAO,aAAA,IAAiB,EAAC;AAAA,IACxC,MAAA,EAAQ,MAAA,CAAO,MAAA,IAAU,EAAC;AAAA,IAC1B,sBAAsB,MAAA,CAAO,oBAAA;AAAA,IAC7B,uBAAuB,MAAA,CAAO;AAAA,GAChC;AACF;;;AC/DA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD;AAKA,SAAS,cAAA,CACP,SACA,MAAA,EACQ;AACR,EAAA,MAAM,QACJ,MAAA,CAAO,YAAA,GAAe,KAAK,GAAA,CAAI,MAAA,CAAO,mBAAmB,OAAO,CAAA;AAClE,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,MAAA,CAAO,QAAQ,CAAA;AACxC;AAcA,eAAsB,wBACpB,MAAA,EAC4B;AAC5B,EAAA,MAAM;AAAA,IACJ,MAAA;AAAA,IACA,OAAA;AAAA,IACA,eAAA;AAAA,IACA,SAAA;AAAA,IACA,aAAA,EAAe,oBAAA;AAAA,IACf,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,SAAS,EAAC;AAAA,IACV,YAAA;AAAA,IACA;AAAA,GACF,GAAI,MAAA;AAEJ,EAAA,MAAM,WAAA,GAAqC;AAAA,IACzC,GAAG,oBAAA;AAAA,IACH,GAAG;AAAA,GACL;AAEA,EAAA,IAAI,aAAA,GAAgB,oBAAA;AACpB,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,IAAI,UAAA,GAAuC,IAAA;AAE3C,EAAA,OAAO,aAAA,CAAc,MAAA,GAAS,CAAA,IAAK,OAAA,GAAU,YAAY,UAAA,EAAY;AACnE,IAAA,OAAA,EAAA;AAGA,IAAA,IAAI,eAAA,EAAiB;AACnB,MAAA,aAAA,GAAgB,MAAM,eAAA;AAAA,QACpB,aAAA;AAAA,QACA,oBAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAE9B,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,OAAA,GAAU,CAAA,EAAG,WAAW,CAAA;AACrD,IAAA,IAAI,UAAU,CAAA,EAAG;AAEf,MAAA,MAAM,MAAM,KAAK,CAAA;AAAA,IACnB;AAGA,IAAA,MAAM,qBAAqB,aAAA,CAAc,GAAA;AAAA,MACvC,CAAC,GAAA,KAAQ,oBAAA,CAAqB,GAAG;AAAA,KACnC;AAGA,IAAA,IAAI;AACF,MAAA,MAAM,WAAA,GAAc,MAAM,0BAAA,CAA2B;AAAA,QACnD,MAAA;AAAA,QACA,OAAA;AAAA,QACA,eAAA;AAAA,QACA,SAAA;AAAA,QACA,YAAA,EAAc,kBAAA;AAAA,QACd;AAAA,OACD,CAAA;AAGD,MAAA,IAAI,UAAA,EAAY;AAEd,QAAA,UAAA,CAAW,iBAAA,CAAkB,IAAA,CAAK,GAAG,WAAA,CAAY,iBAAiB,CAAA;AAElE,QAAA,UAAA,CAAW,iBAAA,CAAkB,IAAA;AAAA,UAC3B,GAAG,YAAY,iBAAA,CAAkB,GAAA,CAAI,CAAC,GAAA,KAAQ,aAAA,CAAc,GAAG,CAAC;AAAA,SAClE;AAEA,QAAA,UAAA,CAAW,aAAA,GAAgB,YAAY,aAAA,CAAc,GAAA;AAAA,UACnD,CAAC,GAAA,KAAQ,aAAA,CAAc,GAAG;AAAA,SAC5B;AAEA,QAAA,UAAA,CAAW,MAAA,CAAO,IAAA;AAAA,UAChB,GAAG,WAAA,CAAY,MAAA,CAAO,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,YAClC,KAAA,EAAO,aAAA,CAAc,GAAA,CAAI,KAAK,CAAA;AAAA,YAC9B,OAAO,GAAA,CAAI;AAAA,WACb,CAAE;AAAA,SACJ;AAAA,MACF,CAAA,MAAO;AACL,QAAA,UAAA,GAAa;AAAA,UACX,GAAG,WAAA;AAAA,UACH,iBAAA,EAAmB,YAAY,iBAAA,CAAkB,GAAA;AAAA,YAC/C,CAAC,GAAA,KAAQ,aAAA,CAAc,GAAG;AAAA,WAC5B;AAAA,UACA,aAAA,EAAe,YAAY,aAAA,CAAc,GAAA;AAAA,YACvC,CAAC,GAAA,KAAQ,aAAA,CAAc,GAAG;AAAA,WAC5B;AAAA,UACA,MAAA,EAAQ,WAAA,CAAY,MAAA,CAAO,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,YACvC,KAAA,EAAO,aAAA,CAAc,GAAA,CAAI,KAAK,CAAA;AAAA,YAC9B,OAAO,GAAA,CAAI;AAAA,WACb,CAAE;AAAA,SACJ;AAAA,MACF;AAGA,MAAA,aAAA,GAAgB,YAAY,aAAA,CAAc,GAAA;AAAA,QACxC,CAAC,GAAA,KAAQ,aAAA,CAAc,GAAG;AAAA,OAC5B;AAAA,IACF,SAAS,KAAA,EAAO;AAEd,MAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,cAAA,EAAiB,OAAO,CAAA,QAAA,CAAA,EAAY,KAAK,CAAA;AAAA,IACzD;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,EACzD;AAEA,EAAA,OAAO,UAAA;AACT;;;AC1IO,SAAS,wBAAwB,EAAA,EAAoC;AAE1E,EAAA,MAAM,QAAA,GAAW,GAAG,IAAA,GAAO,IAAA,CAAK,UAAU,EAAA,CAAG,IAAI,EAAE,MAAA,GAAS,CAAA;AAC5D,EAAA,MAAM,OAAA,GAAU,GAAG,GAAA,GAAM,IAAA,CAAK,UAAU,EAAA,CAAG,GAAG,EAAE,MAAA,GAAS,CAAA;AAIzD,EAAA,MAAM,QAAA,GAAW,GAAA;AAGjB,EAAA,OAAO,IAAA,CAAK,GAAA;AAAA,IACV,WAAW,OAAA,GAAU,QAAA;AAAA,IACrB;AAAA,GACF;AACF;AAKO,SAAS,oBACd,YAAA,EACQ;AAGR,EAAA,MAAM,YAAA,GAAe,GAAA;AACrB,EAAA,MAAM,mBAAmB,YAAA,CAAa,MAAA;AAAA,IACpC,CAAC,GAAA,EAAK,EAAA,KAAO,GAAA,GAAM,wBAAwB,EAAE,CAAA;AAAA,IAC7C;AAAA,GACF;AACA,EAAA,OAAO,YAAA,GAAe,gBAAA;AACxB;AAUO,SAAS,kBACd,YAAA,EAC4B;AAC5B,EAAA,MAAM,UAAsC,EAAC;AAC7C,EAAA,IAAI,eAAyC,EAAC;AAE9C,EAAA,KAAA,MAAW,MAAM,YAAA,EAAc;AAE7B,IAAA,MAAM,WAAA,GAAc,CAAC,GAAG,YAAA,EAAc,EAAE,CAAA;AACxC,IAAA,MAAM,aAAA,GAAgB,oBAAoB,WAAW,CAAA;AAIrD,IAAA,IACE,YAAA,CAAa,MAAA,IAAU,0BAAA,IACvB,aAAA,GAAgB,oBAAA,EAChB;AAEA,MAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,QAAA,OAAA,CAAQ,KAAK,YAAY,CAAA;AACzB,QAAA,YAAA,GAAe,EAAC;AAAA,MAClB;AAAA,IACF;AAIA,IAAA,YAAA,CAAa,KAAK,EAAE,CAAA;AAAA,EACtB;AAGA,EAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,IAAA,OAAA,CAAQ,KAAK,YAAY,CAAA;AAAA,EAC3B;AAEA,EAAA,OAAO,OAAA;AACT;AC3EA,eAAsB,qBACpB,MAAA,EAC+B;AAC/B,EAAA,MAAM;AAAA,IACJ,YAAA;AAAA,IACA,iBAAA;AAAA,IACA,aAAA,GAAgB,qBAAA;AAAA,IAChB,OAAA,GAAU,eAAA;AAAA,IACV;AAAA,GACF,GAAI,MAAA;AAEJ,EAAA,IAAI,iBAAA,CAAkB,WAAW,CAAA,EAAG;AAClC,IAAA,OAAO,EAAC;AAAA,EACV;AAGA,EAAA,IAAI,SAAA,GAAY,CAAA;AAGhB,EAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,GAAA,CAAI,OAAO,IAAA,KAAS;AACrD,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAM,yBAAA,CAA0B,YAAA,EAAc;AAAA,QAC5D,IAAA;AAAA,QACA,aAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAA,SAAA,EAAA;AACA,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,UAAA,CAAW,SAAA,EAAW,kBAAkB,MAAM,CAAA;AAAA,MAChD;AAEA,MAAA,OAAO,EAAE,MAAM,OAAA,EAAQ;AAAA,IACzB,SAAS,KAAA,EAAO;AAEd,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,YAAA,EAAe,IAAI,CAAA,sBAAA,EACjB,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CACvD,CAAA;AAAA,OACF;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AAGD,EAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA;AAE3C,EAAA,OAAO,QAAA;AACT;AClDO,SAAS,qBAAA,CACd,SACA,OAAA,EACkB;AAClB,EAAA,MAAM,MAAA,GAAS,IAAI,UAAA,EAAW;AAC9B,EAAA,sBAAA,CAAuB,MAAA,EAAQ,EAAE,MAAA,EAAQ,OAAA,EAAS,CAAA;AAClD,EAAA,MAAM,gBAAA,GAAmB,oBAAA,CAAqB,KAAA,EAAO,MAAM,CAAA;AAC3D,EAAA,MAAM,UAAA,GAAa,IAAI,cAAA,CAAe,MAAM,CAAA;AAE5C,EAAA,OAAO,EAAE,kBAAkB,UAAA,EAAW;AACxC;;;ACAO,IAAM,cAAN,MAAkB;AAAA,EAIvB,YAAY,OAAA,EAA8C;AACxD,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA;AACtB,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,cAAc,MAAA,EAKqC;AACvD,IAAA,OAAO,kBAAA,CAAmB;AAAA,MACxB,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,MAAA,EAGa;AAC9B,IAAA,OAAO,yBAAA,CAA0B;AAAA,MAC/B,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBAAkB,MAAA,EAOK;AAC3B,IAAA,OAAO,iBAAA,CAAkB;AAAA,MACvB,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,mBAAmB,MAAA,EAKM;AAC7B,IAAA,OAAO,0BAAA,CAA2B;AAAA,MAChC,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,wBAAwB,MAAA,EASC;AAC7B,IAAA,OAAO,uBAAA,CAAwB;AAAA,MAC7B,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,OAAA,EAAuB;AACtC,IAAA,OAAO,qBAAA,CAAsB,OAAA,EAAS,IAAA,CAAK,OAAO,CAAA;AAAA,EACpD;AACF","file":"index.mjs","sourcesContent":["import type { RetryConfig } from \"./types\";\n\n/**\n * EIP-712 domain name for relay session signing\n */\nexport const RELAY_DOMAIN_NAME = \"Net Relay Service\";\n\n/**\n * EIP-712 domain version for relay session signing\n */\nexport const RELAY_DOMAIN_VERSION = \"1\";\n\n/**\n * EIP-712 types for relay session signing\n */\nexport const RELAY_SESSION_TYPES = {\n RelaySession: [\n { name: \"operatorAddress\", type: \"address\" },\n { name: \"secretKeyHash\", type: \"bytes32\" },\n { name: \"expiresAt\", type: \"uint256\" },\n ],\n} as const;\n\n/**\n * Default retry configuration\n */\nexport const DEFAULT_RETRY_CONFIG: Required<RetryConfig> = {\n maxRetries: 3,\n initialDelay: 1000,\n maxDelay: 30000,\n backoffMultiplier: 2,\n};\n\n/**\n * Default number of confirmations to wait for\n */\nexport const DEFAULT_CONFIRMATIONS = 1;\n\n/**\n * Default timeout for waiting for transaction confirmations (milliseconds)\n */\nexport const DEFAULT_TIMEOUT = 60000; // 60 seconds\n\n/**\n * Maximum transactions per batch (matches server limit)\n */\nexport const MAX_TRANSACTIONS_PER_BATCH = 100;\n\n/**\n * Maximum request size in bytes (slightly under 1MB for safety margin)\n */\nexport const MAX_BATCH_SIZE_BYTES = 900 * 1024; // 900KB\n\n/**\n * Maximum size per transaction in bytes\n * Storage transactions can include large data chunks (up to ~200KB per transaction)\n * This cap prevents a single malformed transaction from blocking the entire batch\n */\nexport const MAX_TRANSACTION_SIZE_BYTES = 250 * 1024; // 250KB\n\n","import { keccak256, toBytes } from \"viem\";\nimport type { LocalAccount, Address } from \"viem/accounts\";\nimport {\n RELAY_DOMAIN_NAME,\n RELAY_DOMAIN_VERSION,\n RELAY_SESSION_TYPES,\n} from \"./constants\";\nimport type { CreateSessionResponse, ErrorResponse } from \"./types\";\n\n/**\n * Create a relay session token\n *\n * Signs an EIP-712 message proving ownership of operatorAddress\n * and receives a sessionToken that can be reused for multiple batch requests.\n *\n * @param params - Session creation parameters\n * @returns Session token and expiration timestamp\n * @throws Error if session creation fails\n */\nexport async function createRelaySession(params: {\n apiUrl: string;\n chainId: number;\n operatorAddress: Address;\n secretKey: string;\n account: LocalAccount;\n expiresIn?: number; // seconds, default 3600\n}): Promise<{ sessionToken: string; expiresAt: number }> {\n const { apiUrl, chainId, operatorAddress, secretKey, account, expiresIn } =\n params;\n\n const expiresInSeconds = expiresIn || 3600; // Default 1 hour\n const expiresAt = Math.floor(Date.now() / 1000) + expiresInSeconds;\n const secretKeyHash = keccak256(toBytes(secretKey));\n\n const domain = {\n name: RELAY_DOMAIN_NAME,\n version: RELAY_DOMAIN_VERSION,\n chainId,\n };\n\n const message = {\n operatorAddress,\n secretKeyHash,\n expiresAt: BigInt(expiresAt),\n };\n\n // Sign the typed data using account's signTypedData method\n const signature = await account.signTypedData({\n domain,\n types: RELAY_SESSION_TYPES,\n primaryType: \"RelaySession\",\n message,\n });\n\n // Call session endpoint (send expiresAt - the exact value that was signed)\n const response = await fetch(`${apiUrl}/api/relay/session`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n signature,\n expiresAt, // Send the exact expiresAt that was signed\n }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new Error(\n `Session creation failed: ${response.status} ${\n errorData.error || response.statusText\n }`\n );\n }\n\n const result = (await response.json()) as\n | CreateSessionResponse\n | ErrorResponse;\n if (!result.success || \"error\" in result) {\n throw new Error(\n `Session creation failed: ${\n (\"error\" in result ? result.error : null) || \"Unknown error\"\n }`\n );\n }\n\n if (!result.sessionToken || !result.expiresAt) {\n throw new Error(\n \"Session creation failed: Missing sessionToken or expiresAt in response\"\n );\n }\n\n return {\n sessionToken: result.sessionToken,\n expiresAt: result.expiresAt,\n };\n}\n\n","import type {\n CheckBackendWalletBalanceParams,\n CheckBalanceResult,\n BalanceResponse,\n ErrorResponse,\n} from \"./types\";\n\n/**\n * Check backend wallet balance via relay service\n *\n * This function:\n * 1. Calls /api/relay/balance with operatorAddress and secretKey\n * 2. Returns balance information including sufficientBalance flag\n *\n * @param params - Balance check parameters\n * @returns Result with balance information\n * @throws Error if balance check fails\n */\nexport async function checkBackendWalletBalance(\n params: CheckBackendWalletBalanceParams\n): Promise<CheckBalanceResult> {\n const { apiUrl, chainId, operatorAddress, secretKey } = params;\n\n const response = await fetch(`${apiUrl}/api/relay/balance`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new Error(\n `Balance check endpoint failed: ${response.status} ${JSON.stringify(\n errorData\n )}`\n );\n }\n\n const result = (await response.json()) as BalanceResponse | ErrorResponse;\n if (!result.success || \"error\" in result) {\n throw new Error(\n `Balance check failed: ${(\"error\" in result ? result.error : null) || \"Unknown error\"}`\n );\n }\n\n return {\n backendWalletAddress: result.backendWalletAddress,\n balanceWei: result.balanceWei,\n balanceEth: result.balanceEth,\n sufficientBalance: result.sufficientBalance,\n minRequiredWei: result.minRequiredWei,\n minRequiredEth: result.minRequiredEth,\n };\n}\n\n","import type { Hash } from \"viem\";\nimport type {\n FundBackendWalletParams,\n RelayFundResult,\n FundResponse,\n VerifyFundResponse,\n ErrorResponse,\n} from \"./types\";\n\n/**\n * Extract payment transaction hash from response headers\n */\nfunction extractPaymentTxHash(\n response: Response,\n httpClient: FundBackendWalletParams[\"httpClient\"]\n): string | null {\n try {\n const paymentResponse = httpClient.getPaymentSettleResponse(\n (name: string) => response.headers.get(name)\n );\n return paymentResponse?.transaction || paymentResponse?.txHash || null;\n } catch (error) {\n console.error(\"Failed to extract payment transaction hash:\", error);\n return null;\n }\n}\n\n/**\n * Determine if a verify error is retryable based on HTTP status and error message\n */\nfunction isRetryableVerifyError(\n statusCode: number,\n errorMessage: string\n): boolean {\n // 5xx = always retryable\n if (statusCode >= 500) return true;\n\n // 4xx = check for retryable patterns\n if (statusCode >= 400 && statusCode < 500) {\n const msg = errorMessage.toLowerCase();\n return (\n msg.includes(\"failed to fetch payment transaction\") ||\n msg.includes(\"treasury wallet has insufficient balance\") ||\n msg.includes(\"transferfailed\")\n );\n }\n\n return false;\n}\n\n/**\n * Retry /fund/verify with exponential backoff\n */\nasync function verifyFundWithRetry(\n apiUrl: string,\n paymentTxHash: Hash,\n operatorAddress: string,\n secretKey: string,\n chainId: number\n): Promise<VerifyFundResponse> {\n const maxRetries = 3;\n const initialDelayMs = 2000;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const response = await fetch(`${apiUrl}/api/relay/fund/verify`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n chainId,\n paymentTxHash,\n operatorAddress,\n secretKey,\n }),\n });\n\n const data = (await response.json()) as VerifyFundResponse | ErrorResponse;\n\n if (response.ok && data.success) {\n return data as VerifyFundResponse;\n }\n\n const errorMessage = (data as ErrorResponse).error || \"Unknown error\";\n\n // Don't retry non-retryable errors\n if (!isRetryableVerifyError(response.status, errorMessage)) {\n throw new Error(`Fund verify failed: ${response.status} ${errorMessage}`);\n }\n\n // Last attempt failed\n if (attempt === maxRetries) {\n throw new Error(\n `Fund verify failed after ${maxRetries + 1} attempts: ${errorMessage}`\n );\n }\n\n // Wait before retry (exponential backoff)\n const delayMs = initialDelayMs * Math.pow(2, attempt);\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n throw new Error(\"Verify failed after all retries\");\n}\n\n/**\n * Fund backend wallet via x402 relay service\n *\n * This function:\n * 1. Calls /api/relay/[chainId]/fund with x402 payment (using fetchWithPayment)\n * 2. Extracts paymentTxHash from X-PAYMENT-RESPONSE header\n * 3. Waits for payment confirmation (2 seconds)\n * 4. Calls /api/relay/fund/verify to get backendWalletAddress\n * 5. Returns { paymentTxHash, backendWalletAddress }\n *\n * @param params - Funding parameters\n * @returns Result with paymentTxHash and backendWalletAddress\n * @throws Error if funding fails\n */\nexport async function fundBackendWallet(\n params: FundBackendWalletParams\n): Promise<RelayFundResult> {\n const {\n apiUrl,\n operatorAddress,\n secretKey,\n fetchWithPayment,\n httpClient,\n chainId,\n amount,\n } = params;\n\n // Build URL with optional amount query param\n let fundUrl = `${apiUrl}/api/relay/${chainId}/fund`;\n if (amount !== undefined && amount > 0) {\n fundUrl += `?amount=${amount}`;\n }\n\n console.log(\"💰 Funding backend wallet\", {\n url: fundUrl,\n chainId,\n operatorAddress,\n amount: amount !== undefined ? `$${amount.toFixed(2)}` : \"default\",\n facilitator:\n chainId === 8453\n ? \"Coinbase CDP (Base Mainnet)\"\n : chainId === 84532\n ? \"x402.org (Base Sepolia)\"\n : \"unknown\",\n });\n\n // Step 1: Call /api/relay/[chainId]/fund (Payment)\n let fundResponse: Response;\n try {\n fundResponse = await fetchWithPayment(fundUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n }),\n });\n } catch (error) {\n console.error(\"❌ Fund request failed\", {\n error: error instanceof Error ? error.message : String(error),\n chainId,\n url: fundUrl,\n });\n throw error;\n }\n\n const fundData = (await fundResponse.json()) as FundResponse | ErrorResponse;\n\n // Handle 402 Payment Required\n if (fundResponse.status === 402) {\n // Check if payment was actually processed despite 402\n if (\"payer\" in fundData && fundData.payer) {\n // Payment appears to have been processed\n } else if (\"success\" in fundData && fundData.success) {\n // Payment appears to have been processed\n } else {\n throw new Error(\n `Fund endpoint returned 402 Payment Required: ${JSON.stringify(\n fundData\n )}`\n );\n }\n } else if (!fundResponse.ok) {\n throw new Error(\n `Fund endpoint failed: ${fundResponse.status} ${JSON.stringify(fundData)}`\n );\n }\n\n // Extract payment transaction hash from response headers\n const paymentTxHash = extractPaymentTxHash(fundResponse, httpClient);\n\n if (!paymentTxHash) {\n throw new Error(\n \"Failed to extract payment transaction hash from payment response headers\"\n );\n }\n\n // Step 2: Wait for payment confirmation\n await new Promise((resolve) => setTimeout(resolve, 2000));\n\n // Step 3: Call /api/relay/fund/verify with retry logic\n const verifyData = await verifyFundWithRetry(\n apiUrl,\n paymentTxHash as Hash,\n operatorAddress,\n secretKey,\n chainId\n );\n\n console.log(\"✓ Payment verified and backend wallet funded\", {\n backendWalletAddress: verifyData.backendWalletAddress,\n });\n\n if (!verifyData.backendWalletAddress) {\n throw new Error(\"Backend wallet address not found in verify response\");\n }\n\n return {\n paymentTxHash: paymentTxHash as Hash,\n backendWalletAddress: verifyData.backendWalletAddress,\n };\n}\n","import type { Hash, Address } from \"viem\";\nimport type {\n SubmitTransactionsViaRelayParams,\n RelaySubmitResult,\n SubmitResponse,\n ErrorResponse,\n} from \"./types\";\n\n/**\n * Submit transactions via relay service\n *\n * Calls /api/relay/submit with transactions and returns result\n * with success/failure tracking by index.\n *\n * @param params - Submission parameters\n * @returns Result with transaction hashes and success/failure tracking\n * @throws Error if submission fails\n */\nexport async function submitTransactionsViaRelay(\n params: SubmitTransactionsViaRelayParams\n): Promise<RelaySubmitResult> {\n const {\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n transactions,\n sessionToken,\n } = params;\n\n const response = await fetch(`${apiUrl}/api/relay/submit`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n chainId,\n operatorAddress,\n secretKey,\n transactions: transactions.map((tx) => ({\n ...tx,\n // Only include value if it exists and is > 0\n ...(tx.value !== undefined && tx.value > BigInt(0)\n ? { value: tx.value.toString() }\n : {}),\n })),\n sessionToken,\n }),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new Error(\n `Relay submit endpoint failed: ${response.status} ${JSON.stringify(\n errorData\n )}`\n );\n }\n\n const result = (await response.json()) as SubmitResponse | ErrorResponse;\n if (!result.success || \"error\" in result) {\n throw new Error(\n `Relay submit failed: ${\n (\"error\" in result ? result.error : null) || \"Unknown error\"\n }`\n );\n }\n\n return {\n transactionHashes: result.transactionHashes.map((h: string) => h as Hash),\n successfulIndexes: result.successfulIndexes || [],\n failedIndexes: result.failedIndexes || [],\n errors: result.errors || [],\n backendWalletAddress: result.backendWalletAddress as Address,\n appFeeTransactionHash: result.appFeeTransactionHash as Hash,\n };\n}\n\n","import type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport type { Address } from \"viem\";\nimport type {\n RetryFailedTransactionsParams,\n RetryConfig,\n RelaySubmitResult,\n} from \"./types\";\nimport { DEFAULT_RETRY_CONFIG } from \"./constants\";\nimport { submitTransactionsViaRelay } from \"./submit\";\n\n/**\n * Sleep for specified milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Calculate delay for exponential backoff\n */\nfunction calculateDelay(\n attempt: number,\n config: Required<RetryConfig>\n): number {\n const delay =\n config.initialDelay * Math.pow(config.backoffMultiplier, attempt);\n return Math.min(delay, config.maxDelay);\n}\n\n/**\n * Retry failed transactions with exponential backoff\n *\n * This function:\n * 1. Extracts failed transactions by index from RelaySubmitResult\n * 2. Optionally re-checks on-chain before retry (via recheckFunction)\n * 3. Retries with exponential backoff\n * 4. Handles nested retries\n *\n * @param params - Retry parameters\n * @returns Final success/failure status after retries\n */\nexport async function retryFailedTransactions(\n params: RetryFailedTransactionsParams\n): Promise<RelaySubmitResult> {\n const {\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n failedIndexes: initialFailedIndexes,\n originalTransactions,\n backendWalletAddress,\n config = {},\n sessionToken,\n recheckFunction,\n } = params;\n\n const retryConfig: Required<RetryConfig> = {\n ...DEFAULT_RETRY_CONFIG,\n ...config,\n };\n\n let failedIndexes = initialFailedIndexes;\n let attempt = 0;\n let lastResult: RelaySubmitResult | null = null;\n\n while (failedIndexes.length > 0 && attempt < retryConfig.maxRetries) {\n attempt++;\n\n // Re-check on-chain before retry (if recheckFunction provided)\n if (recheckFunction) {\n failedIndexes = await recheckFunction(\n failedIndexes,\n originalTransactions,\n backendWalletAddress\n );\n }\n\n if (failedIndexes.length === 0) {\n // All transactions have succeeded\n break;\n }\n\n // Calculate delay for exponential backoff\n const delay = calculateDelay(attempt - 1, retryConfig);\n if (attempt > 1) {\n // Don't delay on first attempt\n await sleep(delay);\n }\n\n // Extract failed transactions\n const failedTransactions = failedIndexes.map(\n (idx) => originalTransactions[idx]\n );\n\n // Retry failed transactions\n try {\n const retryResult = await submitTransactionsViaRelay({\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n transactions: failedTransactions,\n sessionToken,\n });\n\n // Merge results\n if (lastResult) {\n // Combine transaction hashes\n lastResult.transactionHashes.push(...retryResult.transactionHashes);\n // Combine successful indexes (adjust for original index)\n lastResult.successfulIndexes.push(\n ...retryResult.successfulIndexes.map((idx) => failedIndexes[idx])\n );\n // Update failed indexes\n lastResult.failedIndexes = retryResult.failedIndexes.map(\n (idx) => failedIndexes[idx]\n );\n // Combine errors\n lastResult.errors.push(\n ...retryResult.errors.map((err) => ({\n index: failedIndexes[err.index],\n error: err.error,\n }))\n );\n } else {\n lastResult = {\n ...retryResult,\n successfulIndexes: retryResult.successfulIndexes.map(\n (idx) => failedIndexes[idx]\n ),\n failedIndexes: retryResult.failedIndexes.map(\n (idx) => failedIndexes[idx]\n ),\n errors: retryResult.errors.map((err) => ({\n index: failedIndexes[err.index],\n error: err.error,\n })),\n };\n }\n\n // Update failed indexes for next iteration\n failedIndexes = retryResult.failedIndexes.map(\n (idx) => failedIndexes[idx]\n );\n } catch (error) {\n // Retry failed, keep current failed indexes\n console.error(`Retry attempt ${attempt} failed:`, error);\n }\n }\n\n if (!lastResult) {\n throw new Error(\"Retry failed: No result after retries\");\n }\n\n return lastResult;\n}\n\n","import type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport {\n MAX_TRANSACTIONS_PER_BATCH,\n MAX_BATCH_SIZE_BYTES,\n MAX_TRANSACTION_SIZE_BYTES,\n} from \"./constants\";\n\n/**\n * Estimate the size of a serialized transaction config in bytes\n *\n * Storage transactions can be large due to:\n * - Large args arrays (chunk data)\n * - Hex-encoded data in args\n * - Full ABI included in each transaction (can be 2-3KB)\n *\n * The entire transaction object is serialized to JSON, including the ABI,\n * so we must account for all fields.\n */\nexport function estimateTransactionSize(tx: WriteTransactionConfig): number {\n // Measure actual sizes of serialized fields\n const argsSize = tx.args ? JSON.stringify(tx.args).length : 0;\n const abiSize = tx.abi ? JSON.stringify(tx.abi).length : 0;\n \n // Add overhead for: to (~44 bytes), functionName (~20 bytes), \n // JSON structure/keys (~100 bytes)\n const overhead = 200;\n\n // Cap at MAX_TRANSACTION_SIZE_BYTES to prevent single transaction from exceeding batch limit\n return Math.min(\n argsSize + abiSize + overhead,\n MAX_TRANSACTION_SIZE_BYTES\n );\n}\n\n/**\n * Estimate the total request size for a batch of transactions\n */\nexport function estimateRequestSize(\n transactions: WriteTransactionConfig[]\n): number {\n // Base overhead: operatorAddress (~42 bytes),\n // secretKey (~50-200 bytes), JSON structure (~100 bytes)\n const baseOverhead = 300;\n const transactionsSize = transactions.reduce(\n (sum, tx) => sum + estimateTransactionSize(tx),\n 0\n );\n return baseOverhead + transactionsSize;\n}\n\n/**\n * Batch transactions into groups that respect count and size limits\n *\n * With 100KB per transaction estimate:\n * - Size limit: ~9 transactions per batch (900KB / 100KB)\n * - Count limit: 100 transactions per batch\n * - Size limit is the constraining factor for large transactions\n */\nexport function batchTransactions(\n transactions: WriteTransactionConfig[]\n): WriteTransactionConfig[][] {\n const batches: WriteTransactionConfig[][] = [];\n let currentBatch: WriteTransactionConfig[] = [];\n\n for (const tx of transactions) {\n // Calculate what the batch size would be with this transaction added\n const batchWithTx = [...currentBatch, tx];\n const estimatedSize = estimateRequestSize(batchWithTx);\n\n // Check if adding this transaction would exceed limits\n // Size limit is typically the constraining factor (9 transactions @ 100KB each)\n if (\n currentBatch.length >= MAX_TRANSACTIONS_PER_BATCH ||\n estimatedSize > MAX_BATCH_SIZE_BYTES\n ) {\n // Start a new batch\n if (currentBatch.length > 0) {\n batches.push(currentBatch);\n currentBatch = [];\n }\n }\n\n // If a single transaction exceeds the batch size limit, we still add it\n // (it will be its own batch, and the server will reject it with a clear error)\n currentBatch.push(tx);\n }\n\n // Add the last batch if it has transactions\n if (currentBatch.length > 0) {\n batches.push(currentBatch);\n }\n\n return batches;\n}\n\n","import { waitForTransactionReceipt } from \"viem/actions\";\nimport type { Hash } from \"viem\";\nimport type {\n WaitForConfirmationsParams,\n ConfirmationResult,\n} from \"./types\";\nimport { DEFAULT_CONFIRMATIONS, DEFAULT_TIMEOUT } from \"./constants\";\n\n/**\n * Wait for transaction confirmations\n *\n * Uses waitForTransactionReceipt() from viem/actions to wait for\n * multiple transactions in parallel. Handles timeouts and tracks progress.\n *\n * @param params - Confirmation parameters\n * @returns Array of transaction receipts\n * @throws Error if timeout occurs or transaction fails\n */\nexport async function waitForConfirmations(\n params: WaitForConfirmationsParams\n): Promise<ConfirmationResult[]> {\n const {\n publicClient,\n transactionHashes,\n confirmations = DEFAULT_CONFIRMATIONS,\n timeout = DEFAULT_TIMEOUT,\n onProgress,\n } = params;\n\n if (transactionHashes.length === 0) {\n return [];\n }\n\n const results: ConfirmationResult[] = [];\n let confirmed = 0;\n\n // Wait for all transactions in parallel\n const promises = transactionHashes.map(async (hash) => {\n try {\n const receipt = await waitForTransactionReceipt(publicClient, {\n hash,\n confirmations,\n timeout,\n });\n\n confirmed++;\n if (onProgress) {\n onProgress(confirmed, transactionHashes.length);\n }\n\n return { hash, receipt };\n } catch (error) {\n // Transaction failed or timed out\n throw new Error(\n `Transaction ${hash} failed or timed out: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n });\n\n // Wait for all promises\n const receipts = await Promise.all(promises);\n\n return receipts;\n}\n\n","import { x402Client, wrapFetchWithPayment, x402HTTPClient } from \"@x402/fetch\";\nimport { registerExactEvmScheme } from \"@x402/evm/exact/client\";\nimport type { LocalAccount } from \"viem/accounts\";\nimport type { X402ClientResult } from \"../types\";\n\n/**\n * Create x402 client for relay payments\n *\n * Sets up x402Client with user's account, registers EVM scheme,\n * and returns wrapped fetch function and HTTP client for header extraction.\n *\n * @param account - User's local account (from privateKeyToAccount)\n * @param chainId - Chain ID (optional, for logging purposes)\n * @returns Object with fetchWithPayment and httpClient\n */\nexport function createRelayX402Client(\n account: LocalAccount,\n chainId?: number\n): X402ClientResult {\n const client = new x402Client();\n registerExactEvmScheme(client, { signer: account });\n const fetchWithPayment = wrapFetchWithPayment(fetch, client);\n const httpClient = new x402HTTPClient(client);\n\n return { fetchWithPayment, httpClient };\n}\n\n","import type { LocalAccount, Address } from \"viem/accounts\";\nimport type { PublicClient, Hash } from \"viem\";\nimport type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport { createRelaySession } from \"../session\";\nimport { checkBackendWalletBalance } from \"../balance\";\nimport { fundBackendWallet } from \"../fund\";\nimport { submitTransactionsViaRelay } from \"../submit\";\nimport { retryFailedTransactions } from \"../retry\";\nimport { createRelayX402Client } from \"./x402Client\";\nimport type {\n CheckBalanceResult,\n RelayFundResult,\n RelaySubmitResult,\n RetryFailedTransactionsParams,\n RetryConfig,\n FundBackendWalletParams,\n SubmitTransactionsViaRelayParams,\n} from \"../types\";\n\n/**\n * High-level client for Net Relay Service\n *\n * Provides a convenient class-based API that stores apiUrl and chainId,\n * reducing boilerplate when making multiple relay calls.\n */\nexport class RelayClient {\n private apiUrl: string;\n private chainId: number;\n\n constructor(options: { apiUrl: string; chainId: number }) {\n this.apiUrl = options.apiUrl;\n this.chainId = options.chainId;\n }\n\n /**\n * Create a relay session token\n *\n * @param params - Session creation parameters (apiUrl and chainId are already set)\n * @returns Session token and expiration timestamp\n */\n async createSession(params: {\n operatorAddress: Address;\n secretKey: string;\n account: LocalAccount;\n expiresIn?: number;\n }): Promise<{ sessionToken: string; expiresAt: number }> {\n return createRelaySession({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Check backend wallet balance\n *\n * @param params - Balance check parameters (apiUrl and chainId are already set)\n * @returns Result with balance information\n */\n async checkBalance(params: {\n operatorAddress: Address;\n secretKey: string;\n }): Promise<CheckBalanceResult> {\n return checkBackendWalletBalance({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Fund backend wallet via x402 payment\n *\n * @param params - Funding parameters (apiUrl and chainId are already set)\n * @returns Result with paymentTxHash and backendWalletAddress\n */\n async fundBackendWallet(params: {\n operatorAddress: Address;\n secretKey: string;\n fetchWithPayment: typeof fetch;\n httpClient: FundBackendWalletParams[\"httpClient\"];\n /** Optional custom USDC amount. If not provided, uses default minimum. */\n amount?: number;\n }): Promise<RelayFundResult> {\n return fundBackendWallet({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Submit transactions via relay\n *\n * @param params - Submission parameters (apiUrl and chainId are already set)\n * @returns Result with transaction hashes and success/failure tracking\n */\n async submitTransactions(params: {\n operatorAddress: Address;\n secretKey: string;\n transactions: WriteTransactionConfig[];\n sessionToken: string;\n }): Promise<RelaySubmitResult> {\n return submitTransactionsViaRelay({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Retry failed transactions with exponential backoff\n *\n * @param params - Retry parameters (apiUrl and chainId are already set)\n * @returns Final success/failure status after retries\n */\n async retryFailedTransactions(params: {\n operatorAddress: Address;\n secretKey: string;\n failedIndexes: number[];\n originalTransactions: WriteTransactionConfig[];\n backendWalletAddress: Address;\n config?: RetryConfig;\n sessionToken: string;\n recheckFunction?: RetryFailedTransactionsParams[\"recheckFunction\"];\n }): Promise<RelaySubmitResult> {\n return retryFailedTransactions({\n apiUrl: this.apiUrl,\n chainId: this.chainId,\n ...params,\n });\n }\n\n /**\n * Create x402 client for relay payments\n *\n * @param account - User's local account\n * @returns Object with fetchWithPayment and httpClient\n */\n createX402Client(account: LocalAccount) {\n return createRelayX402Client(account, this.chainId);\n }\n}\n\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@net-protocol/relay",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Net Relay SDK for submitting transactions via x402 payment relay service",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",