@usdctofiat/offramp 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -131,4 +131,4 @@ Every deposit is automatically delegated to the Delegate vault for oracle-based
131
131
 
132
132
  [usdctofiat.xyz](https://usdctofiat.xyz) · [delegate.usdctofiat.xyz](https://delegate.usdctofiat.xyz) · [peerlytics.xyz](https://peerlytics.xyz) · [orderbook.peerlytics.xyz](https://orderbook.peerlytics.xyz)
133
133
 
134
- [Examples & agent skills](https://github.com/ADWilkinson/usdctofiat-peerlytics-starters) · [@usdctofiat](https://x.com/usdctofiat) · [@davyjones0x](https://x.com/davyjones0x)
134
+ [Examples & agent skills](https://github.com/ADWilkinson/usdctofiat-peerlytics-starters) · [@usdctofiat](https://x.com/usdctofiat) · [@andrewwilkinson](https://x.com/andrewwilkinson)
@@ -1,12 +1,3 @@
1
- // src/platforms.ts
2
- import {
3
- currencyInfo,
4
- getCurrencyInfoFromHash,
5
- getPaymentMethodsCatalog,
6
- resolvePaymentMethodHash
7
- } from "@zkp2p/sdk";
8
- import { z } from "zod";
9
-
10
1
  // src/config.ts
11
2
  import { getContracts, getGatingServiceAddress } from "@zkp2p/sdk";
12
3
  var BASE_CHAIN_ID = 8453;
@@ -33,6 +24,13 @@ var INDEXER_MAX_DELAY_MS = 1e4;
33
24
  var PAYEE_REGISTRATION_TIMEOUT_MS = 8e3;
34
25
 
35
26
  // src/platforms.ts
27
+ import {
28
+ currencyInfo,
29
+ getCurrencyInfoFromHash,
30
+ getPaymentMethodsCatalog,
31
+ resolvePaymentMethodHash
32
+ } from "@zkp2p/sdk";
33
+ import { z } from "zod";
36
34
  var PAYMENT_CATALOG = getPaymentMethodsCatalog(BASE_CHAIN_ID, RUNTIME_ENV);
37
35
  var ZELLE_HASH_LOOKUP_NAMES = ["zelle", "zelle-bofa", "zelle-chase", "zelle-citi"];
38
36
  var FALLBACK_CURRENCIES = {
@@ -344,7 +342,8 @@ function isUserCancellation(error) {
344
342
  }
345
343
 
346
344
  // src/otc.ts
347
- import { isAddress, zeroAddress } from "viem";
345
+ import { createPublicClient, http, isAddress, zeroAddress } from "viem";
346
+ import { base } from "viem/chains";
348
347
 
349
348
  // ../../node_modules/@zkp2p/contracts-v2/abis/base/WhitelistPreIntentHook.json
350
349
  var WhitelistPreIntentHook_default = [
@@ -626,14 +625,21 @@ var WhitelistPreIntentHook_default = [
626
625
  type: "uint256"
627
626
  },
628
627
  {
629
- internalType: "address",
630
- name: "referrer",
631
- type: "address"
632
- },
633
- {
634
- internalType: "uint256",
635
- name: "referrerFee",
636
- type: "uint256"
628
+ components: [
629
+ {
630
+ internalType: "address",
631
+ name: "recipient",
632
+ type: "address"
633
+ },
634
+ {
635
+ internalType: "uint256",
636
+ name: "fee",
637
+ type: "uint256"
638
+ }
639
+ ],
640
+ internalType: "struct IReferralFee.ReferralFee[]",
641
+ name: "referralFees",
642
+ type: "tuple[]"
637
643
  },
638
644
  {
639
645
  internalType: "bytes",
@@ -682,20 +688,123 @@ var WhitelistPreIntentHook_default = [
682
688
  }
683
689
  ];
684
690
 
685
- // src/deposit.ts
686
- import { createPublicClient, decodeEventLog, formatUnits as formatUnits2, http, parseUnits } from "viem";
687
- import { base } from "viem/chains";
688
- import {
689
- OfframpClient,
690
- getSpreadOracleConfig,
691
- mapConversionRatesToOnchainMinRate
692
- } from "@zkp2p/sdk";
691
+ // src/sdk-client.ts
692
+ import { OfframpClient } from "@zkp2p/sdk";
693
+ function createSdkClient(walletClient) {
694
+ return new OfframpClient({
695
+ walletClient,
696
+ chainId: BASE_CHAIN_ID,
697
+ runtimeEnv: RUNTIME_ENV,
698
+ rpcUrl: BASE_RPC_URL,
699
+ baseApiUrl: API_BASE_URL
700
+ });
701
+ }
702
+
703
+ // src/otc.ts
704
+ var WHITELIST_HOOK_ADDRESS = "0xda023Ea0d789A41BcF5866F7B6BBd2CaDF9b79B8";
705
+ var OTC_BASE_URL = "https://usdctofiat.xyz";
706
+ async function enableOtc(walletClient, depositId, takerAddress, escrowAddress) {
707
+ if (!isAddress(takerAddress)) {
708
+ throw new OfframpError("Invalid taker address", "VALIDATION");
709
+ }
710
+ const escrow = escrowAddress || ESCROW_ADDRESS;
711
+ const taker = takerAddress;
712
+ const depositIdBig = BigInt(depositId);
713
+ const client = createSdkClient(walletClient);
714
+ const txOverrides = { referrer: [REFERRER] };
715
+ try {
716
+ const currentHook = await client.getDepositWhitelistHook(depositIdBig, {
717
+ escrowAddress: escrow
718
+ });
719
+ if (currentHook !== zeroAddress) {
720
+ const isAlready = await readIsWhitelisted(escrow, depositIdBig, taker);
721
+ if (isAlready) {
722
+ return {
723
+ depositId,
724
+ takerAddress: taker,
725
+ otcLink: getOtcLink(depositId, escrow)
726
+ };
727
+ }
728
+ }
729
+ await writeContract(walletClient, "addToWhitelist", [escrow, depositIdBig, [taker]]);
730
+ if (currentHook === zeroAddress) {
731
+ await client.setDepositWhitelistHook({
732
+ depositId: depositIdBig,
733
+ whitelistHook: WHITELIST_HOOK_ADDRESS,
734
+ escrowAddress: escrow,
735
+ txOverrides
736
+ });
737
+ }
738
+ return {
739
+ depositId,
740
+ takerAddress: taker,
741
+ otcLink: getOtcLink(depositId, escrow)
742
+ };
743
+ } catch (err) {
744
+ if (err instanceof OfframpError) throw err;
745
+ if (isUserCancellation(err)) {
746
+ throw new OfframpError("User cancelled", "USER_CANCELLED", void 0, err, { depositId });
747
+ }
748
+ const detail = err instanceof Error ? err.message : String(err);
749
+ throw new OfframpError(`Failed to enable OTC: ${detail}`, "DEPOSIT_FAILED", void 0, err, {
750
+ depositId
751
+ });
752
+ }
753
+ }
754
+ async function disableOtc(walletClient, depositId, escrowAddress) {
755
+ const escrow = escrowAddress || ESCROW_ADDRESS;
756
+ const client = createSdkClient(walletClient);
757
+ const txOverrides = { referrer: [REFERRER] };
758
+ try {
759
+ await client.setDepositWhitelistHook({
760
+ depositId: BigInt(depositId),
761
+ whitelistHook: zeroAddress,
762
+ escrowAddress: escrow,
763
+ txOverrides
764
+ });
765
+ } catch (err) {
766
+ if (isUserCancellation(err)) {
767
+ throw new OfframpError("User cancelled", "USER_CANCELLED", void 0, err, { depositId });
768
+ }
769
+ const detail = err instanceof Error ? err.message : String(err);
770
+ throw new OfframpError(`Failed to disable OTC: ${detail}`, "DEPOSIT_FAILED", void 0, err, {
771
+ depositId
772
+ });
773
+ }
774
+ }
775
+ function getOtcLink(depositId, escrowAddress) {
776
+ const escrow = escrowAddress || ESCROW_ADDRESS;
777
+ return `${OTC_BASE_URL}/deposit/${escrow}/${depositId}`;
778
+ }
779
+ async function writeContract(walletClient, functionName, args) {
780
+ const wc = walletClient;
781
+ if (typeof wc.writeContract !== "function") {
782
+ throw new OfframpError("Wallet client does not support writeContract", "VALIDATION");
783
+ }
784
+ await wc.writeContract({
785
+ address: WHITELIST_HOOK_ADDRESS,
786
+ abi: WhitelistPreIntentHook_default,
787
+ functionName,
788
+ args
789
+ });
790
+ }
791
+ async function readIsWhitelisted(escrow, depositId, taker) {
792
+ const publicClient = createPublicClient({ chain: base, transport: http(BASE_RPC_URL) });
793
+ return publicClient.readContract({
794
+ address: WHITELIST_HOOK_ADDRESS,
795
+ abi: WhitelistPreIntentHook_default,
796
+ functionName: "isWhitelisted",
797
+ args: [escrow, depositId, taker]
798
+ });
799
+ }
693
800
 
694
801
  // src/queries.ts
695
- import { formatUnits } from "viem";
802
+ import { concatHex, createPublicClient as createPublicClient2, encodeFunctionData, formatUnits, http as http2 } from "viem";
803
+ import { base as base2 } from "viem/chains";
696
804
  import {
697
805
  classifyDelegationState,
698
806
  defaultIndexerEndpoint,
807
+ getAttributionDataSuffix,
699
808
  getCurrencyInfoFromHash as getCurrencyInfoFromHash2,
700
809
  IndexerClient,
701
810
  IndexerDepositService
@@ -772,6 +881,18 @@ function extractTxHash(result) {
772
881
  return result.transactionHash;
773
882
  throw new Error("Unexpected transaction result format");
774
883
  }
884
+ var ESCROW_V2_ABI = [
885
+ {
886
+ name: "clearRateManager",
887
+ type: "function",
888
+ stateMutability: "nonpayable",
889
+ inputs: [{ name: "depositId", type: "uint256" }],
890
+ outputs: []
891
+ }
892
+ ];
893
+ function appendReferrerAttribution(calldata) {
894
+ return concatHex([calldata, getAttributionDataSuffix([REFERRER])]);
895
+ }
775
896
  async function deposits(walletAddress) {
776
897
  const service = getIndexerService();
777
898
  const raw = await service.fetchDepositsWithRelations(
@@ -794,8 +915,65 @@ async function close(walletClient, depositId, escrowAddress) {
794
915
  });
795
916
  return extractTxHash(result);
796
917
  }
918
+ async function delegate(walletClient, depositId, escrowAddress) {
919
+ const client = createSdkClient(walletClient);
920
+ const result = await client.setRateManager({
921
+ depositId: BigInt(depositId),
922
+ rateManagerAddress: RATE_MANAGER_REGISTRY_ADDRESS,
923
+ rateManagerId: DELEGATE_RATE_MANAGER_ID,
924
+ escrowAddress: escrowAddress || ESCROW_ADDRESS,
925
+ txOverrides: { referrer: [REFERRER] }
926
+ });
927
+ return extractTxHash(result);
928
+ }
929
+ async function undelegate(walletClient, depositId, escrowAddress) {
930
+ const account = walletClient.account;
931
+ if (!account) {
932
+ throw new Error("Wallet client has no account. Connect a wallet first.");
933
+ }
934
+ const data = appendReferrerAttribution(
935
+ encodeFunctionData({
936
+ abi: ESCROW_V2_ABI,
937
+ functionName: "clearRateManager",
938
+ args: [BigInt(depositId)]
939
+ })
940
+ );
941
+ const hash = await walletClient.sendTransaction({
942
+ account,
943
+ chain: base2,
944
+ data,
945
+ to: escrowAddress || ESCROW_ADDRESS
946
+ });
947
+ const publicClient = createPublicClient2({
948
+ chain: base2,
949
+ transport: http2(BASE_RPC_URL)
950
+ });
951
+ try {
952
+ const receipt = await publicClient.waitForTransactionReceipt({
953
+ hash,
954
+ confirmations: 1,
955
+ timeout: 12e4,
956
+ pollingInterval: 4e3
957
+ });
958
+ if (receipt.status !== "success") {
959
+ throw new Error("Undelegation transaction failed");
960
+ }
961
+ } catch (err) {
962
+ const isTimeout = err instanceof Error && err.message.toLowerCase().includes("timed out");
963
+ if (!isTimeout) {
964
+ throw err;
965
+ }
966
+ }
967
+ return hash;
968
+ }
797
969
 
798
970
  // src/deposit.ts
971
+ import { createPublicClient as createPublicClient3, decodeEventLog, formatUnits as formatUnits2, http as http3, parseUnits } from "viem";
972
+ import { base as base3 } from "viem/chains";
973
+ import {
974
+ getSpreadOracleConfig,
975
+ mapConversionRatesToOnchainMinRate
976
+ } from "@zkp2p/sdk";
799
977
  function usdcToUnits(amount) {
800
978
  return parseUnits(amount, 6);
801
979
  }
@@ -890,15 +1068,6 @@ function extractTxHash2(result) {
890
1068
  return result.transactionHash;
891
1069
  throw new Error("Unexpected transaction result format");
892
1070
  }
893
- function createSdkClient(walletClient) {
894
- return new OfframpClient({
895
- walletClient,
896
- chainId: BASE_CHAIN_ID,
897
- runtimeEnv: RUNTIME_ENV,
898
- rpcUrl: BASE_RPC_URL,
899
- baseApiUrl: API_BASE_URL
900
- });
901
- }
902
1071
  async function findUndelegatedDeposit(walletAddress) {
903
1072
  try {
904
1073
  const service = getIndexerService();
@@ -907,6 +1076,7 @@ async function findUndelegatedDeposit(walletAddress) {
907
1076
  { limit: 50 }
908
1077
  );
909
1078
  const escrowLower = ESCROW_ADDRESS.toLowerCase();
1079
+ const delegateIdLower = DELEGATE_RATE_MANAGER_ID.toLowerCase();
910
1080
  const undelegated = (raw || []).filter((d) => {
911
1081
  if (d.status === "CLOSED") return false;
912
1082
  if (d.escrowAddress.toLowerCase() !== escrowLower) return false;
@@ -918,7 +1088,7 @@ async function findUndelegatedDeposit(walletAddress) {
918
1088
  }
919
1089
  })();
920
1090
  if (remaining === 0n) return false;
921
- return d.rateManagerId !== DELEGATE_RATE_MANAGER_ID;
1091
+ return (d.rateManagerId ?? "").toLowerCase() !== delegateIdLower;
922
1092
  });
923
1093
  undelegated.sort((a, b) => Number(BigInt(b.depositId) - BigInt(a.depositId)));
924
1094
  return undelegated[0] ?? null;
@@ -983,7 +1153,7 @@ async function offramp(walletClient, params, onProgress) {
983
1153
  const minUnits = usdcToUnits(String(MIN_ORDER_USDC));
984
1154
  const maxUnits = usdcToUnits(String(Math.min(amt, 2500)));
985
1155
  try {
986
- const publicClient = createPublicClient({ chain: base, transport: http(BASE_RPC_URL) });
1156
+ const publicClient = createPublicClient3({ chain: base3, transport: http3(BASE_RPC_URL) });
987
1157
  const balance = await publicClient.readContract({
988
1158
  address: USDC_ADDRESS,
989
1159
  abi: [
@@ -1048,8 +1218,8 @@ async function offramp(walletClient, params, onProgress) {
1048
1218
  retainOnEmpty: false,
1049
1219
  intentAmountRange: { min: minUnits, max: maxUnits },
1050
1220
  processorNames: [platformId],
1051
- depositData: [buildDepositData(platformId, normalizedIdentifier)],
1052
1221
  conversionRates,
1222
+ payeeDetailsHashes: [hashedOnchainId],
1053
1223
  paymentMethodsOverride: [methodHash],
1054
1224
  paymentMethodDataOverride: [
1055
1225
  {
@@ -1172,122 +1342,17 @@ async function offramp(walletClient, params, onProgress) {
1172
1342
  return { depositId, txHash: hash, resumed: false, otcLink };
1173
1343
  }
1174
1344
 
1175
- // src/otc.ts
1176
- var WHITELIST_HOOK_ADDRESS = "0xda023Ea0d789A41BcF5866F7B6BBd2CaDF9b79B8";
1177
- var OTC_BASE_URL = "https://usdctofiat.xyz";
1178
- async function enableOtc(walletClient, depositId, takerAddress, escrowAddress) {
1179
- if (!isAddress(takerAddress)) {
1180
- throw new OfframpError("Invalid taker address", "VALIDATION");
1181
- }
1182
- const escrow = escrowAddress || ESCROW_ADDRESS;
1183
- const taker = takerAddress;
1184
- const depositIdBig = BigInt(depositId);
1185
- const client = createSdkClient(walletClient);
1186
- const txOverrides = { referrer: [REFERRER] };
1187
- try {
1188
- const currentHook = await client.getDepositWhitelistHook(depositIdBig, {
1189
- escrowAddress: escrow
1190
- });
1191
- if (currentHook !== zeroAddress) {
1192
- const isAlready = await readIsWhitelisted(
1193
- walletClient,
1194
- escrow,
1195
- depositIdBig,
1196
- taker
1197
- );
1198
- if (isAlready) {
1199
- return {
1200
- depositId,
1201
- takerAddress: taker,
1202
- otcLink: getOtcLink2(depositId, escrow)
1203
- };
1204
- }
1205
- }
1206
- await writeContract(walletClient, "addToWhitelist", [escrow, depositIdBig, [taker]]);
1207
- if (currentHook === zeroAddress) {
1208
- await client.setDepositWhitelistHook({
1209
- depositId: depositIdBig,
1210
- whitelistHook: WHITELIST_HOOK_ADDRESS,
1211
- escrowAddress: escrow,
1212
- txOverrides
1213
- });
1214
- }
1215
- return {
1216
- depositId,
1217
- takerAddress: taker,
1218
- otcLink: getOtcLink2(depositId, escrow)
1219
- };
1220
- } catch (err) {
1221
- if (err instanceof OfframpError) throw err;
1222
- if (isUserCancellation(err)) {
1223
- throw new OfframpError("User cancelled", "USER_CANCELLED", void 0, err, { depositId });
1224
- }
1225
- const detail = err instanceof Error ? err.message : String(err);
1226
- throw new OfframpError(`Failed to enable OTC: ${detail}`, "DEPOSIT_FAILED", void 0, err, {
1227
- depositId
1228
- });
1229
- }
1230
- }
1231
- async function disableOtc(walletClient, depositId, escrowAddress) {
1232
- const escrow = escrowAddress || ESCROW_ADDRESS;
1233
- const client = createSdkClient(walletClient);
1234
- const txOverrides = { referrer: [REFERRER] };
1235
- try {
1236
- await client.setDepositWhitelistHook({
1237
- depositId: BigInt(depositId),
1238
- whitelistHook: zeroAddress,
1239
- escrowAddress: escrow,
1240
- txOverrides
1241
- });
1242
- } catch (err) {
1243
- if (isUserCancellation(err)) {
1244
- throw new OfframpError("User cancelled", "USER_CANCELLED", void 0, err, { depositId });
1245
- }
1246
- const detail = err instanceof Error ? err.message : String(err);
1247
- throw new OfframpError(`Failed to disable OTC: ${detail}`, "DEPOSIT_FAILED", void 0, err, {
1248
- depositId
1249
- });
1250
- }
1251
- }
1252
- function getOtcLink2(depositId, escrowAddress) {
1253
- const escrow = escrowAddress || ESCROW_ADDRESS;
1254
- return `${OTC_BASE_URL}/deposit/${escrow}/${depositId}`;
1255
- }
1256
- async function writeContract(walletClient, functionName, args) {
1257
- const wc = walletClient;
1258
- if (typeof wc.writeContract !== "function") {
1259
- throw new OfframpError("Wallet client does not support writeContract", "VALIDATION");
1260
- }
1261
- await wc.writeContract({
1262
- address: WHITELIST_HOOK_ADDRESS,
1263
- abi: WhitelistPreIntentHook_default,
1264
- functionName,
1265
- args
1266
- });
1267
- }
1268
- async function readIsWhitelisted(walletClient, escrow, depositId, taker) {
1269
- const { createPublicClient: createPublicClient2, http: http2 } = await import("viem");
1270
- const { base: base2 } = await import("viem/chains");
1271
- const publicClient = createPublicClient2({
1272
- chain: base2,
1273
- transport: http2("https://mainnet.base.org")
1274
- });
1275
- return publicClient.readContract({
1276
- address: WHITELIST_HOOK_ADDRESS,
1277
- abi: WhitelistPreIntentHook_default,
1278
- functionName: "isWhitelisted",
1279
- args: [escrow, depositId, taker]
1280
- });
1281
- }
1282
-
1283
1345
  export {
1346
+ ESCROW_ADDRESS,
1284
1347
  PLATFORMS,
1285
1348
  OfframpError,
1286
1349
  enableOtc,
1287
1350
  disableOtc,
1288
- getOtcLink2 as getOtcLink,
1351
+ getOtcLink,
1289
1352
  deposits,
1290
1353
  close,
1354
+ delegate,
1355
+ undelegate,
1291
1356
  offramp
1292
1357
  };
1293
- //# sourceMappingURL=chunk-2XJXFOPJ.js.map
1358
+ //# sourceMappingURL=chunk-OJY6DE3I.js.map