@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 +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +243 -18
- package/dist/index.mjs +243 -18
- package/package.json +1 -1
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
|
-
|
|
38
|
-
type
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
38
|
-
type
|
|
39
|
-
|
|
40
|
-
|
|
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 =
|
|
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 =
|
|
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 ===
|
|
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 ===
|
|
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
|
-
|
|
1414
|
-
|
|
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()
|
|
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 =
|
|
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 =
|
|
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 ===
|
|
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 ===
|
|
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
|
-
|
|
1390
|
-
|
|
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()
|
|
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
|