@primuslabs/fund-js-sdk 0.1.4 → 0.1.6

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
@@ -34,10 +34,11 @@ declare global {
34
34
  //
35
35
  // ERC20_TYPE = 0;
36
36
  // NATIVE_TYPE = 1;
37
- type TokenType = 0 | 1
38
- type TokenInfo =
39
- | { tokenType: 0; tokenAddress: string }
40
- | { tokenType: 1; tokenAddress?: string };
37
+ // ERC721_TYPE = 2;
38
+ type TokenType = 0 | 1 | 2
39
+ type TokenInfo = { tokenType: 0; tokenAddress: string }
40
+ | { tokenType: 1; tokenAddress?: string }
41
+ | { tokenType: 2; tokenAddress: string };
41
42
 
42
43
  type RecipientBaseInfo = {
43
44
  socialPlatform: string;// The name of the social platform.
package/dist/index.d.ts CHANGED
@@ -34,10 +34,11 @@ declare global {
34
34
  //
35
35
  // ERC20_TYPE = 0;
36
36
  // NATIVE_TYPE = 1;
37
- type TokenType = 0 | 1
38
- type TokenInfo =
39
- | { tokenType: 0; tokenAddress: string }
40
- | { tokenType: 1; tokenAddress?: string };
37
+ // ERC721_TYPE = 2;
38
+ type TokenType = 0 | 1 | 2
39
+ type TokenInfo = { tokenType: 0; tokenAddress: string }
40
+ | { tokenType: 1; tokenAddress?: string }
41
+ | { tokenType: 2; tokenAddress: string };
41
42
 
42
43
  type RecipientBaseInfo = {
43
44
  socialPlatform: string;// The name of the social platform.
package/dist/index.js CHANGED
@@ -42,6 +42,10 @@ var DATASOURCETEMPLATESMAP = {
42
42
  "google account": {
43
43
  id: "3bad8a55-4415-4bec-9b47-a4c7bbe93518",
44
44
  field: "2"
45
+ },
46
+ xiaohongshu: {
47
+ id: "93c6e6df-63ab-41af-8cba-f2927c0d2f1c",
48
+ field: "red_id"
45
49
  }
46
50
  };
47
51
  var SUPPORTEDSOCIALPLATFORMS = Object.keys(DATASOURCETEMPLATESMAP);
@@ -80,6 +84,16 @@ var SUPPORTEDCHAINIDS = Object.keys(Fund_CONTRACTS).map((i) => Number(i));
80
84
 
81
85
  // src/classes/Contract.ts
82
86
  var import_ethers = require("ethers");
87
+
88
+ // src/utils/utils.ts
89
+ var hasErrorFlagFn = (curErrorArr, targetErrorStrArr) => {
90
+ return curErrorArr.some((curErrorStr) => {
91
+ let f = targetErrorStrArr.some((targetErrorStr) => curErrorStr.toLowerCase().includes(targetErrorStr.toLowerCase()));
92
+ return f;
93
+ });
94
+ };
95
+
96
+ // src/classes/Contract.ts
83
97
  var Contract = class {
84
98
  address;
85
99
  provider;
@@ -132,19 +146,23 @@ var Contract = class {
132
146
  } catch (error) {
133
147
  console.log("sendTransaction error:", error);
134
148
  const errStr = error?.message || error?.toString()?.toLowerCase() || "";
149
+ const errorMsg1 = typeof error === "string" ? error : error instanceof Error ? error.message : typeof error.message === "string" ? error.message : JSON.stringify(error);
150
+ const errorMsg2 = typeof error === "object" ? JSON.stringify(error) : error?.toString();
151
+ const curErrorStrArr = [errorMsg1, errorMsg2];
135
152
  const userRejectErrStrArr = ["user rejected", "approval denied"];
136
- const isUserRejected = userRejectErrStrArr.some((str) => errStr.indexOf(str) > -1);
153
+ const isUserRejected = hasErrorFlagFn(curErrorStrArr, userRejectErrStrArr);
137
154
  if (error?.code === "ACTION_REJECTED" || isUserRejected) {
138
155
  return reject("user rejected transaction");
139
156
  }
157
+ const isNoPendingWithdrawals = hasErrorFlagFn(curErrorStrArr, ["no pending withdrawals"]);
158
+ if (isNoPendingWithdrawals) {
159
+ return reject("no pending withdrawals");
160
+ }
140
161
  const insufficientBalanceErrStrArr = ["insufficient balance", "unpredictable_gas_limit"];
141
- const isInsufficientBalance = insufficientBalanceErrStrArr.some((str) => errStr.indexOf(str) > -1);
162
+ const isInsufficientBalance = hasErrorFlagFn(curErrorStrArr, insufficientBalanceErrStrArr);
142
163
  if (isInsufficientBalance) {
143
164
  return reject("insufficient balance");
144
165
  }
145
- if (errStr.indexOf("no pending withdrawals") > -1) {
146
- return reject("no pending withdrawals");
147
- }
148
166
  return reject(error);
149
167
  }
150
168
  });
@@ -1139,6 +1157,190 @@ var erc20Abi_default = [
1139
1157
  }
1140
1158
  ];
1141
1159
 
1160
+ // src/config/erc721Abi.json
1161
+ var erc721Abi_default = [
1162
+ {
1163
+ type: "function",
1164
+ name: "supportsInterface",
1165
+ stateMutability: "view",
1166
+ inputs: [
1167
+ { internalType: "bytes4", name: "interfaceId", type: "bytes4" }
1168
+ ],
1169
+ outputs: [{ internalType: "bool", name: "", type: "bool" }]
1170
+ },
1171
+ {
1172
+ type: "function",
1173
+ name: "balanceOf",
1174
+ stateMutability: "view",
1175
+ inputs: [
1176
+ { internalType: "address", name: "owner", type: "address" }
1177
+ ],
1178
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }]
1179
+ },
1180
+ {
1181
+ type: "function",
1182
+ name: "ownerOf",
1183
+ stateMutability: "view",
1184
+ inputs: [
1185
+ { internalType: "uint256", name: "tokenId", type: "uint256" }
1186
+ ],
1187
+ outputs: [{ internalType: "address", name: "", type: "address" }]
1188
+ },
1189
+ {
1190
+ type: "function",
1191
+ name: "tokenURI",
1192
+ stateMutability: "view",
1193
+ inputs: [
1194
+ { internalType: "uint256", name: "tokenId", type: "uint256" }
1195
+ ],
1196
+ outputs: [{ internalType: "string", name: "", type: "string" }]
1197
+ },
1198
+ {
1199
+ type: "function",
1200
+ name: "approve",
1201
+ stateMutability: "nonpayable",
1202
+ inputs: [
1203
+ { internalType: "address", name: "to", type: "address" },
1204
+ { internalType: "uint256", name: "tokenId", type: "uint256" }
1205
+ ],
1206
+ outputs: []
1207
+ },
1208
+ {
1209
+ type: "function",
1210
+ name: "getApproved",
1211
+ stateMutability: "view",
1212
+ inputs: [
1213
+ { internalType: "uint256", name: "tokenId", type: "uint256" }
1214
+ ],
1215
+ outputs: [{ internalType: "address", name: "", type: "address" }]
1216
+ },
1217
+ {
1218
+ type: "function",
1219
+ name: "setApprovalForAll",
1220
+ stateMutability: "nonpayable",
1221
+ inputs: [
1222
+ { internalType: "address", name: "operator", type: "address" },
1223
+ { internalType: "bool", name: "approved", type: "bool" }
1224
+ ],
1225
+ outputs: []
1226
+ },
1227
+ {
1228
+ type: "function",
1229
+ name: "isApprovedForAll",
1230
+ stateMutability: "view",
1231
+ inputs: [
1232
+ { internalType: "address", name: "owner", type: "address" },
1233
+ { internalType: "address", name: "operator", type: "address" }
1234
+ ],
1235
+ outputs: [{ internalType: "bool", name: "", type: "bool" }]
1236
+ },
1237
+ {
1238
+ type: "function",
1239
+ name: "transferFrom",
1240
+ stateMutability: "nonpayable",
1241
+ inputs: [
1242
+ { internalType: "address", name: "from", type: "address" },
1243
+ { internalType: "address", name: "to", type: "address" },
1244
+ { internalType: "uint256", name: "tokenId", type: "uint256" }
1245
+ ],
1246
+ outputs: []
1247
+ },
1248
+ {
1249
+ type: "function",
1250
+ name: "safeTransferFrom",
1251
+ stateMutability: "nonpayable",
1252
+ inputs: [
1253
+ { internalType: "address", name: "from", type: "address" },
1254
+ { internalType: "address", name: "to", type: "address" },
1255
+ { internalType: "uint256", name: "tokenId", type: "uint256" }
1256
+ ],
1257
+ outputs: []
1258
+ },
1259
+ {
1260
+ type: "function",
1261
+ name: "name",
1262
+ stateMutability: "view",
1263
+ inputs: [],
1264
+ outputs: [{ internalType: "string", name: "", type: "string" }]
1265
+ },
1266
+ {
1267
+ type: "function",
1268
+ name: "symbol",
1269
+ stateMutability: "view",
1270
+ inputs: [],
1271
+ outputs: [{ internalType: "string", name: "", type: "string" }]
1272
+ }
1273
+ ];
1274
+
1275
+ // src/classes/Erc721Contract.ts
1276
+ var Erc721Contract = class {
1277
+ contractInstance;
1278
+ constructor(provider, address) {
1279
+ if (!provider || !address) {
1280
+ throw new Error("provider, address are required");
1281
+ }
1282
+ this.contractInstance = new Contract_default(provider, address, erc721Abi_default);
1283
+ }
1284
+ async approve(address, tokenId) {
1285
+ return new Promise(async (resolve, reject) => {
1286
+ try {
1287
+ const approver = await this.contractInstance.callMethod("getApproved", [tokenId]);
1288
+ if (approver === address) {
1289
+ console.log(`Already approved:: ${approver}`);
1290
+ resolve("Approved");
1291
+ } else {
1292
+ await this.contractInstance.sendTransaction("approve", [address, tokenId]);
1293
+ console.log(`Approved`);
1294
+ resolve("Approved");
1295
+ }
1296
+ } catch (error) {
1297
+ console.error("Approval failed:", error);
1298
+ return reject(error);
1299
+ }
1300
+ });
1301
+ }
1302
+ // ownerAddress: string,
1303
+ async setApprovalForAll(operatorAddress) {
1304
+ return new Promise(async (resolve, reject) => {
1305
+ try {
1306
+ await this.contractInstance.sendTransaction("setApprovalForAll", [operatorAddress, true]);
1307
+ console.log(`Approved`);
1308
+ resolve("Approved");
1309
+ } catch (error) {
1310
+ console.error("Approval failed:", error);
1311
+ return reject(error);
1312
+ }
1313
+ });
1314
+ }
1315
+ async fetchMetaData(nftContractAddress, tokenId) {
1316
+ return new Promise(async (resolve, reject) => {
1317
+ try {
1318
+ let url = await this.contractInstance.callMethod("tokenURI", [tokenId]);
1319
+ if (url.startsWith("ipfs://")) {
1320
+ url = url.replace("ipfs://", "https://ipfs.io/ipfs/");
1321
+ }
1322
+ const res = await fetch(url);
1323
+ if (!res.ok) {
1324
+ return reject(`Failed to fetch metadata from ${url}`);
1325
+ }
1326
+ let metadata = await res.json();
1327
+ if (metadata.image && metadata.image.startsWith("ipfs://")) {
1328
+ metadata.image = metadata.image.replace(
1329
+ "ipfs://",
1330
+ "https://ipfs.io/ipfs/"
1331
+ );
1332
+ }
1333
+ metadata.address = nftContractAddress;
1334
+ metadata.tokenId = tokenId;
1335
+ return resolve(metadata);
1336
+ } catch (error) {
1337
+ return reject(error);
1338
+ }
1339
+ });
1340
+ }
1341
+ };
1342
+ var Erc721Contract_default = Erc721Contract;
1343
+
1142
1344
  // src/classes/Fund.ts
1143
1345
  var { parseUnits, formatUnits } = import_ethers2.ethers.utils;
1144
1346
  var Fund = class {
@@ -1202,18 +1404,22 @@ var Fund = class {
1202
1404
  const web3Provider = new import_ethers2.ethers.providers.Web3Provider(this.provider);
1203
1405
  const erc20Contract = new import_ethers2.ethers.Contract(tokenInfo.tokenAddress, erc20Abi_default, web3Provider);
1204
1406
  decimals = await erc20Contract.decimals();
1407
+ } else if (tokenInfo.tokenType === 2) {
1408
+ decimals = 0;
1409
+ const erc721ContractInstance = new Erc721Contract_default(this.provider, tokenInfo.tokenAddress);
1410
+ await erc721ContractInstance.approve(this.fundContract.address, recipientInfo.nftIds[0]);
1205
1411
  }
1206
1412
  const tokenAmount = parseUnits(recipientInfo.tokenAmount.toString(), decimals);
1207
1413
  const newFundRecipientInfo = {
1208
1414
  idSource: recipientInfo.socialPlatform,
1209
1415
  id: recipientInfo.userIdentifier,
1210
1416
  amount: tokenAmount,
1211
- nftIds: []
1417
+ nftIds: recipientInfo.nftIds
1212
1418
  };
1213
- if (tokenInfo.tokenType === 0) {
1214
- params = [tokenInfo, newFundRecipientInfo];
1215
- } else {
1419
+ if (tokenInfo.tokenType === 1) {
1216
1420
  params = [tokenInfo, newFundRecipientInfo, { value: tokenAmount }];
1421
+ } else {
1422
+ params = [tokenInfo, newFundRecipientInfo];
1217
1423
  }
1218
1424
  const result = await this.fundContract.sendTransaction("tip", params);
1219
1425
  resolve(result);
@@ -1249,6 +1455,10 @@ var Fund = class {
1249
1455
  const web3Provider = new import_ethers2.ethers.providers.Web3Provider(this.provider);
1250
1456
  const erc20Contract = new import_ethers2.ethers.Contract(tokenInfo.tokenAddress, erc20Abi_default, web3Provider);
1251
1457
  decimals = await erc20Contract.decimals();
1458
+ } else if (tokenInfo.tokenType === 2) {
1459
+ decimals = 0;
1460
+ const erc721ContractInstance = new Erc721Contract_default(this.provider, tokenInfo.tokenAddress);
1461
+ await erc721ContractInstance.setApprovalForAll(this.fundContract.address);
1252
1462
  }
1253
1463
  let totalFormatAmount = recipientInfoList.reduce((acc, cur) => acc.add(parseUnits(cur.tokenAmount.toString(), decimals)), import_ethers2.ethers.BigNumber.from(0));
1254
1464
  const newRecipientInfoList = recipientInfoList.map((i) => {
@@ -1257,13 +1467,13 @@ var Fund = class {
1257
1467
  idSource: i.socialPlatform,
1258
1468
  id: i.userIdentifier,
1259
1469
  amount: formatAmount,
1260
- nftIds: []
1470
+ nftIds: i.nftIds
1261
1471
  };
1262
1472
  });
1263
- if (tokenInfo.tokenType === 0) {
1264
- params = [tokenInfo, newRecipientInfoList];
1265
- } else {
1473
+ if (tokenInfo.tokenType === 1) {
1266
1474
  params = [tokenInfo, newRecipientInfoList, { value: totalFormatAmount }];
1475
+ } else {
1476
+ params = [tokenInfo, newRecipientInfoList];
1267
1477
  }
1268
1478
  const result = await this.fundContract.sendTransaction("tipBatch", params);
1269
1479
  return resolve(result);
@@ -1406,16 +1616,28 @@ var Fund = class {
1406
1616
  console.log("fundRecords", fundRecords);
1407
1617
  let formatRecords = [];
1408
1618
  for (const record of fundRecords) {
1409
- const { tipper, timestamp, tipToken: [tokenType, tokenAddress], amount } = record;
1619
+ const { tipper, timestamp, tipToken: [tokenType, tokenAddress], amount, nftIds } = record;
1410
1620
  let decimals = 18;
1411
1621
  let symbol = "";
1622
+ let tokenId = null;
1623
+ let nftInfo = null;
1412
1624
  if (tokenType === 0) {
1413
- const web3Provider = new import_ethers2.ethers.providers.Web3Provider(this.provider);
1414
- const erc20Contract = new import_ethers2.ethers.Contract(tokenAddress, erc20Abi_default, web3Provider);
1625
+ let formatProvider;
1626
+ if (this.provider instanceof import_ethers2.ethers.providers.JsonRpcProvider) {
1627
+ formatProvider = this.provider;
1628
+ } else {
1629
+ formatProvider = new import_ethers2.ethers.providers.Web3Provider(this.provider);
1630
+ }
1631
+ const erc20Contract = new import_ethers2.ethers.Contract(tokenAddress, erc20Abi_default, formatProvider);
1415
1632
  decimals = await erc20Contract.decimals();
1416
1633
  symbol = await erc20Contract.symbol();
1417
1634
  } else if (tokenType === 1) {
1418
1635
  symbol = NATIVETOKENS[this.chainId];
1636
+ } else if (tokenType === 2) {
1637
+ decimals = 0;
1638
+ tokenId = parseInt(nftIds[0]);
1639
+ const erc721ContractInstance = new Erc721Contract_default(this.provider, tokenAddress);
1640
+ nftInfo = await erc721ContractInstance.fetchMetaData(tokenAddress, tokenId);
1419
1641
  }
1420
1642
  let fundToken = {
1421
1643
  tokenType,
@@ -1427,11 +1649,14 @@ var Fund = class {
1427
1649
  if (tokenType === 0) {
1428
1650
  fundToken.tokenAddress = tokenAddress;
1429
1651
  }
1652
+ if (tokenType === 2) {
1653
+ Object.assign(fundToken, nftInfo ?? {});
1654
+ }
1430
1655
  formatRecords.push({
1431
1656
  funder: tipper,
1432
1657
  fundToken,
1433
1658
  amount: formatUnits(amount, decimals),
1434
- timestamp: timestamp.toNumber() * 1e3
1659
+ timestamp: timestamp.toNumber()
1435
1660
  });
1436
1661
  }
1437
1662
  console.log("formatRecords", formatRecords);
@@ -1483,7 +1708,7 @@ var PrimusFund = class {
1483
1708
  formatUserIdentifier = i.userIdentifier.slice(1);
1484
1709
  }
1485
1710
  return {
1486
- nftIds: [],
1711
+ nftIds: i.nftIds ?? [],
1487
1712
  socialPlatform: formatSocialPlatform,
1488
1713
  userIdentifier: formatUserIdentifier,
1489
1714
  tokenAmount: i.tokenAmount
package/dist/index.mjs CHANGED
@@ -18,6 +18,10 @@ var DATASOURCETEMPLATESMAP = {
18
18
  "google account": {
19
19
  id: "3bad8a55-4415-4bec-9b47-a4c7bbe93518",
20
20
  field: "2"
21
+ },
22
+ xiaohongshu: {
23
+ id: "93c6e6df-63ab-41af-8cba-f2927c0d2f1c",
24
+ field: "red_id"
21
25
  }
22
26
  };
23
27
  var SUPPORTEDSOCIALPLATFORMS = Object.keys(DATASOURCETEMPLATESMAP);
@@ -56,6 +60,16 @@ var SUPPORTEDCHAINIDS = Object.keys(Fund_CONTRACTS).map((i) => Number(i));
56
60
 
57
61
  // src/classes/Contract.ts
58
62
  import { ethers } from "ethers";
63
+
64
+ // src/utils/utils.ts
65
+ var hasErrorFlagFn = (curErrorArr, targetErrorStrArr) => {
66
+ return curErrorArr.some((curErrorStr) => {
67
+ let f = targetErrorStrArr.some((targetErrorStr) => curErrorStr.toLowerCase().includes(targetErrorStr.toLowerCase()));
68
+ return f;
69
+ });
70
+ };
71
+
72
+ // src/classes/Contract.ts
59
73
  var Contract = class {
60
74
  address;
61
75
  provider;
@@ -108,19 +122,23 @@ var Contract = class {
108
122
  } catch (error) {
109
123
  console.log("sendTransaction error:", error);
110
124
  const errStr = error?.message || error?.toString()?.toLowerCase() || "";
125
+ const errorMsg1 = typeof error === "string" ? error : error instanceof Error ? error.message : typeof error.message === "string" ? error.message : JSON.stringify(error);
126
+ const errorMsg2 = typeof error === "object" ? JSON.stringify(error) : error?.toString();
127
+ const curErrorStrArr = [errorMsg1, errorMsg2];
111
128
  const userRejectErrStrArr = ["user rejected", "approval denied"];
112
- const isUserRejected = userRejectErrStrArr.some((str) => errStr.indexOf(str) > -1);
129
+ const isUserRejected = hasErrorFlagFn(curErrorStrArr, userRejectErrStrArr);
113
130
  if (error?.code === "ACTION_REJECTED" || isUserRejected) {
114
131
  return reject("user rejected transaction");
115
132
  }
133
+ const isNoPendingWithdrawals = hasErrorFlagFn(curErrorStrArr, ["no pending withdrawals"]);
134
+ if (isNoPendingWithdrawals) {
135
+ return reject("no pending withdrawals");
136
+ }
116
137
  const insufficientBalanceErrStrArr = ["insufficient balance", "unpredictable_gas_limit"];
117
- const isInsufficientBalance = insufficientBalanceErrStrArr.some((str) => errStr.indexOf(str) > -1);
138
+ const isInsufficientBalance = hasErrorFlagFn(curErrorStrArr, insufficientBalanceErrStrArr);
118
139
  if (isInsufficientBalance) {
119
140
  return reject("insufficient balance");
120
141
  }
121
- if (errStr.indexOf("no pending withdrawals") > -1) {
122
- return reject("no pending withdrawals");
123
- }
124
142
  return reject(error);
125
143
  }
126
144
  });
@@ -1115,6 +1133,190 @@ var erc20Abi_default = [
1115
1133
  }
1116
1134
  ];
1117
1135
 
1136
+ // src/config/erc721Abi.json
1137
+ var erc721Abi_default = [
1138
+ {
1139
+ type: "function",
1140
+ name: "supportsInterface",
1141
+ stateMutability: "view",
1142
+ inputs: [
1143
+ { internalType: "bytes4", name: "interfaceId", type: "bytes4" }
1144
+ ],
1145
+ outputs: [{ internalType: "bool", name: "", type: "bool" }]
1146
+ },
1147
+ {
1148
+ type: "function",
1149
+ name: "balanceOf",
1150
+ stateMutability: "view",
1151
+ inputs: [
1152
+ { internalType: "address", name: "owner", type: "address" }
1153
+ ],
1154
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }]
1155
+ },
1156
+ {
1157
+ type: "function",
1158
+ name: "ownerOf",
1159
+ stateMutability: "view",
1160
+ inputs: [
1161
+ { internalType: "uint256", name: "tokenId", type: "uint256" }
1162
+ ],
1163
+ outputs: [{ internalType: "address", name: "", type: "address" }]
1164
+ },
1165
+ {
1166
+ type: "function",
1167
+ name: "tokenURI",
1168
+ stateMutability: "view",
1169
+ inputs: [
1170
+ { internalType: "uint256", name: "tokenId", type: "uint256" }
1171
+ ],
1172
+ outputs: [{ internalType: "string", name: "", type: "string" }]
1173
+ },
1174
+ {
1175
+ type: "function",
1176
+ name: "approve",
1177
+ stateMutability: "nonpayable",
1178
+ inputs: [
1179
+ { internalType: "address", name: "to", type: "address" },
1180
+ { internalType: "uint256", name: "tokenId", type: "uint256" }
1181
+ ],
1182
+ outputs: []
1183
+ },
1184
+ {
1185
+ type: "function",
1186
+ name: "getApproved",
1187
+ stateMutability: "view",
1188
+ inputs: [
1189
+ { internalType: "uint256", name: "tokenId", type: "uint256" }
1190
+ ],
1191
+ outputs: [{ internalType: "address", name: "", type: "address" }]
1192
+ },
1193
+ {
1194
+ type: "function",
1195
+ name: "setApprovalForAll",
1196
+ stateMutability: "nonpayable",
1197
+ inputs: [
1198
+ { internalType: "address", name: "operator", type: "address" },
1199
+ { internalType: "bool", name: "approved", type: "bool" }
1200
+ ],
1201
+ outputs: []
1202
+ },
1203
+ {
1204
+ type: "function",
1205
+ name: "isApprovedForAll",
1206
+ stateMutability: "view",
1207
+ inputs: [
1208
+ { internalType: "address", name: "owner", type: "address" },
1209
+ { internalType: "address", name: "operator", type: "address" }
1210
+ ],
1211
+ outputs: [{ internalType: "bool", name: "", type: "bool" }]
1212
+ },
1213
+ {
1214
+ type: "function",
1215
+ name: "transferFrom",
1216
+ stateMutability: "nonpayable",
1217
+ inputs: [
1218
+ { internalType: "address", name: "from", type: "address" },
1219
+ { internalType: "address", name: "to", type: "address" },
1220
+ { internalType: "uint256", name: "tokenId", type: "uint256" }
1221
+ ],
1222
+ outputs: []
1223
+ },
1224
+ {
1225
+ type: "function",
1226
+ name: "safeTransferFrom",
1227
+ stateMutability: "nonpayable",
1228
+ inputs: [
1229
+ { internalType: "address", name: "from", type: "address" },
1230
+ { internalType: "address", name: "to", type: "address" },
1231
+ { internalType: "uint256", name: "tokenId", type: "uint256" }
1232
+ ],
1233
+ outputs: []
1234
+ },
1235
+ {
1236
+ type: "function",
1237
+ name: "name",
1238
+ stateMutability: "view",
1239
+ inputs: [],
1240
+ outputs: [{ internalType: "string", name: "", type: "string" }]
1241
+ },
1242
+ {
1243
+ type: "function",
1244
+ name: "symbol",
1245
+ stateMutability: "view",
1246
+ inputs: [],
1247
+ outputs: [{ internalType: "string", name: "", type: "string" }]
1248
+ }
1249
+ ];
1250
+
1251
+ // src/classes/Erc721Contract.ts
1252
+ var Erc721Contract = class {
1253
+ contractInstance;
1254
+ constructor(provider, address) {
1255
+ if (!provider || !address) {
1256
+ throw new Error("provider, address are required");
1257
+ }
1258
+ this.contractInstance = new Contract_default(provider, address, erc721Abi_default);
1259
+ }
1260
+ async approve(address, tokenId) {
1261
+ return new Promise(async (resolve, reject) => {
1262
+ try {
1263
+ const approver = await this.contractInstance.callMethod("getApproved", [tokenId]);
1264
+ if (approver === address) {
1265
+ console.log(`Already approved:: ${approver}`);
1266
+ resolve("Approved");
1267
+ } else {
1268
+ await this.contractInstance.sendTransaction("approve", [address, tokenId]);
1269
+ console.log(`Approved`);
1270
+ resolve("Approved");
1271
+ }
1272
+ } catch (error) {
1273
+ console.error("Approval failed:", error);
1274
+ return reject(error);
1275
+ }
1276
+ });
1277
+ }
1278
+ // ownerAddress: string,
1279
+ async setApprovalForAll(operatorAddress) {
1280
+ return new Promise(async (resolve, reject) => {
1281
+ try {
1282
+ await this.contractInstance.sendTransaction("setApprovalForAll", [operatorAddress, true]);
1283
+ console.log(`Approved`);
1284
+ resolve("Approved");
1285
+ } catch (error) {
1286
+ console.error("Approval failed:", error);
1287
+ return reject(error);
1288
+ }
1289
+ });
1290
+ }
1291
+ async fetchMetaData(nftContractAddress, tokenId) {
1292
+ return new Promise(async (resolve, reject) => {
1293
+ try {
1294
+ let url = await this.contractInstance.callMethod("tokenURI", [tokenId]);
1295
+ if (url.startsWith("ipfs://")) {
1296
+ url = url.replace("ipfs://", "https://ipfs.io/ipfs/");
1297
+ }
1298
+ const res = await fetch(url);
1299
+ if (!res.ok) {
1300
+ return reject(`Failed to fetch metadata from ${url}`);
1301
+ }
1302
+ let metadata = await res.json();
1303
+ if (metadata.image && metadata.image.startsWith("ipfs://")) {
1304
+ metadata.image = metadata.image.replace(
1305
+ "ipfs://",
1306
+ "https://ipfs.io/ipfs/"
1307
+ );
1308
+ }
1309
+ metadata.address = nftContractAddress;
1310
+ metadata.tokenId = tokenId;
1311
+ return resolve(metadata);
1312
+ } catch (error) {
1313
+ return reject(error);
1314
+ }
1315
+ });
1316
+ }
1317
+ };
1318
+ var Erc721Contract_default = Erc721Contract;
1319
+
1118
1320
  // src/classes/Fund.ts
1119
1321
  var { parseUnits, formatUnits } = ethers2.utils;
1120
1322
  var Fund = class {
@@ -1178,18 +1380,22 @@ var Fund = class {
1178
1380
  const web3Provider = new ethers2.providers.Web3Provider(this.provider);
1179
1381
  const erc20Contract = new ethers2.Contract(tokenInfo.tokenAddress, erc20Abi_default, web3Provider);
1180
1382
  decimals = await erc20Contract.decimals();
1383
+ } else if (tokenInfo.tokenType === 2) {
1384
+ decimals = 0;
1385
+ const erc721ContractInstance = new Erc721Contract_default(this.provider, tokenInfo.tokenAddress);
1386
+ await erc721ContractInstance.approve(this.fundContract.address, recipientInfo.nftIds[0]);
1181
1387
  }
1182
1388
  const tokenAmount = parseUnits(recipientInfo.tokenAmount.toString(), decimals);
1183
1389
  const newFundRecipientInfo = {
1184
1390
  idSource: recipientInfo.socialPlatform,
1185
1391
  id: recipientInfo.userIdentifier,
1186
1392
  amount: tokenAmount,
1187
- nftIds: []
1393
+ nftIds: recipientInfo.nftIds
1188
1394
  };
1189
- if (tokenInfo.tokenType === 0) {
1190
- params = [tokenInfo, newFundRecipientInfo];
1191
- } else {
1395
+ if (tokenInfo.tokenType === 1) {
1192
1396
  params = [tokenInfo, newFundRecipientInfo, { value: tokenAmount }];
1397
+ } else {
1398
+ params = [tokenInfo, newFundRecipientInfo];
1193
1399
  }
1194
1400
  const result = await this.fundContract.sendTransaction("tip", params);
1195
1401
  resolve(result);
@@ -1225,6 +1431,10 @@ var Fund = class {
1225
1431
  const web3Provider = new ethers2.providers.Web3Provider(this.provider);
1226
1432
  const erc20Contract = new ethers2.Contract(tokenInfo.tokenAddress, erc20Abi_default, web3Provider);
1227
1433
  decimals = await erc20Contract.decimals();
1434
+ } else if (tokenInfo.tokenType === 2) {
1435
+ decimals = 0;
1436
+ const erc721ContractInstance = new Erc721Contract_default(this.provider, tokenInfo.tokenAddress);
1437
+ await erc721ContractInstance.setApprovalForAll(this.fundContract.address);
1228
1438
  }
1229
1439
  let totalFormatAmount = recipientInfoList.reduce((acc, cur) => acc.add(parseUnits(cur.tokenAmount.toString(), decimals)), ethers2.BigNumber.from(0));
1230
1440
  const newRecipientInfoList = recipientInfoList.map((i) => {
@@ -1233,13 +1443,13 @@ var Fund = class {
1233
1443
  idSource: i.socialPlatform,
1234
1444
  id: i.userIdentifier,
1235
1445
  amount: formatAmount,
1236
- nftIds: []
1446
+ nftIds: i.nftIds
1237
1447
  };
1238
1448
  });
1239
- if (tokenInfo.tokenType === 0) {
1240
- params = [tokenInfo, newRecipientInfoList];
1241
- } else {
1449
+ if (tokenInfo.tokenType === 1) {
1242
1450
  params = [tokenInfo, newRecipientInfoList, { value: totalFormatAmount }];
1451
+ } else {
1452
+ params = [tokenInfo, newRecipientInfoList];
1243
1453
  }
1244
1454
  const result = await this.fundContract.sendTransaction("tipBatch", params);
1245
1455
  return resolve(result);
@@ -1382,16 +1592,28 @@ var Fund = class {
1382
1592
  console.log("fundRecords", fundRecords);
1383
1593
  let formatRecords = [];
1384
1594
  for (const record of fundRecords) {
1385
- const { tipper, timestamp, tipToken: [tokenType, tokenAddress], amount } = record;
1595
+ const { tipper, timestamp, tipToken: [tokenType, tokenAddress], amount, nftIds } = record;
1386
1596
  let decimals = 18;
1387
1597
  let symbol = "";
1598
+ let tokenId = null;
1599
+ let nftInfo = null;
1388
1600
  if (tokenType === 0) {
1389
- const web3Provider = new ethers2.providers.Web3Provider(this.provider);
1390
- const erc20Contract = new ethers2.Contract(tokenAddress, erc20Abi_default, web3Provider);
1601
+ let formatProvider;
1602
+ if (this.provider instanceof ethers2.providers.JsonRpcProvider) {
1603
+ formatProvider = this.provider;
1604
+ } else {
1605
+ formatProvider = new ethers2.providers.Web3Provider(this.provider);
1606
+ }
1607
+ const erc20Contract = new ethers2.Contract(tokenAddress, erc20Abi_default, formatProvider);
1391
1608
  decimals = await erc20Contract.decimals();
1392
1609
  symbol = await erc20Contract.symbol();
1393
1610
  } else if (tokenType === 1) {
1394
1611
  symbol = NATIVETOKENS[this.chainId];
1612
+ } else if (tokenType === 2) {
1613
+ decimals = 0;
1614
+ tokenId = parseInt(nftIds[0]);
1615
+ const erc721ContractInstance = new Erc721Contract_default(this.provider, tokenAddress);
1616
+ nftInfo = await erc721ContractInstance.fetchMetaData(tokenAddress, tokenId);
1395
1617
  }
1396
1618
  let fundToken = {
1397
1619
  tokenType,
@@ -1403,11 +1625,14 @@ var Fund = class {
1403
1625
  if (tokenType === 0) {
1404
1626
  fundToken.tokenAddress = tokenAddress;
1405
1627
  }
1628
+ if (tokenType === 2) {
1629
+ Object.assign(fundToken, nftInfo ?? {});
1630
+ }
1406
1631
  formatRecords.push({
1407
1632
  funder: tipper,
1408
1633
  fundToken,
1409
1634
  amount: formatUnits(amount, decimals),
1410
- timestamp: timestamp.toNumber() * 1e3
1635
+ timestamp: timestamp.toNumber()
1411
1636
  });
1412
1637
  }
1413
1638
  console.log("formatRecords", formatRecords);
@@ -1459,7 +1684,7 @@ var PrimusFund = class {
1459
1684
  formatUserIdentifier = i.userIdentifier.slice(1);
1460
1685
  }
1461
1686
  return {
1462
- nftIds: [],
1687
+ nftIds: i.nftIds ?? [],
1463
1688
  socialPlatform: formatSocialPlatform,
1464
1689
  userIdentifier: formatUserIdentifier,
1465
1690
  tokenAmount: i.tokenAmount
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primuslabs/fund-js-sdk",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "author": "Primus Labs <dev@primuslabs.org>",
5
5
  "description": "Primus fund js sdk",
6
6
  "repository": {