Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f3b8d4d532 | ||
![]() |
ebbb376f47 | ||
![]() |
61e0314974 | ||
![]() |
244f7e4629 | ||
![]() |
d7d9d264d5 | ||
![]() |
e30a47f309 | ||
![]() |
b4a434b12b |
14
patches/web3-core-method+1.7.4.patch
Normal file
14
patches/web3-core-method+1.7.4.patch
Normal file
@ -0,0 +1,14 @@
|
||||
diff --git a/node_modules/web3-core-method/lib/index.js b/node_modules/web3-core-method/lib/index.js
|
||||
index 84cb1c3..4eb4592 100644
|
||||
--- a/node_modules/web3-core-method/lib/index.js
|
||||
+++ b/node_modules/web3-core-method/lib/index.js
|
||||
@@ -561,6 +561,9 @@ Method.prototype.buildCall = function () {
|
||||
};
|
||||
// SENDS the SIGNED SIGNATURE
|
||||
var sendSignedTx = function (sign) {
|
||||
+ var returnObj = Object.assign({}, payload.params[0]);
|
||||
+ returnObj.transactionHash = sign.transactionHash;
|
||||
+ defer.eventEmitter.emit('presend', returnObj);
|
||||
var signedPayload = { ...payload,
|
||||
method: 'eth_sendRawTransaction',
|
||||
params: [sign.rawTransaction]
|
18
src/abis/abiFeeAddress.ts
Normal file
18
src/abis/abiFeeAddress.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { AbiItem } from "web3-utils";
|
||||
|
||||
export let abiEvolveFactory: AbiItem[] = [
|
||||
{
|
||||
inputs: [],
|
||||
name: "feeToAddress",
|
||||
outputs: [
|
||||
{
|
||||
internalType: "address",
|
||||
name: "",
|
||||
type: "address",
|
||||
},
|
||||
],
|
||||
stateMutability: "view",
|
||||
type: "function",
|
||||
constant: true,
|
||||
},
|
||||
];
|
17
src/api/RecordApi.ts
Normal file
17
src/api/RecordApi.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { WALLET_API_HOST } from "../config/constants";
|
||||
import { DELETE_JSON, POST_JSON } from "../lib/Http";
|
||||
|
||||
export function saveRecord(data) {
|
||||
const url = `${WALLET_API_HOST}/trans/record`;
|
||||
return POST_JSON(url, data);
|
||||
}
|
||||
|
||||
export function records(data) {
|
||||
const url = `${WALLET_API_HOST}/trans/records`;
|
||||
return POST_JSON(url, data);
|
||||
}
|
||||
|
||||
export function removeRecord(data) {
|
||||
const url = `${WALLET_API_HOST}/trans/record`;
|
||||
return DELETE_JSON(url, data);
|
||||
}
|
107
src/common/AsyncQueue.ts
Normal file
107
src/common/AsyncQueue.ts
Normal file
@ -0,0 +1,107 @@
|
||||
type Callback<T> = () => Promise<T>
|
||||
|
||||
export type AsyncQueue<T = void> = {
|
||||
push: (task: Callback<T>) => Promise<T>
|
||||
flush: () => Promise<void>
|
||||
size: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that each callback pushed onto the queue is executed in series.
|
||||
* Such a quetie 😻
|
||||
* @param opts.dedupeConcurrent If dedupeConcurrent is `true` it ensures that if multiple
|
||||
* tasks are pushed onto the queue while there is an active task, only the
|
||||
* last one will be executed, once the active task has completed.
|
||||
* e.g. in the below example, only 0 and 3 will be executed.
|
||||
* ```
|
||||
* const queue = createAsyncQueue({ dedupeConcurrent: true })
|
||||
* queue.push(async () => console.log(0)) // returns 0
|
||||
* queue.push(async () => console.log(1)) // returns 3
|
||||
* queue.push(async () => console.log(2)) // returns 3
|
||||
* queue.push(async () => console.log(3)) // returns 3
|
||||
* ```
|
||||
* */
|
||||
export function createAsyncQueue<T = void>(opts = { dedupeConcurrent: false }): AsyncQueue<T> {
|
||||
const { dedupeConcurrent } = opts
|
||||
let queue: Callback<T>[] = []
|
||||
let running: Promise<void> | undefined
|
||||
let nextPromise = new DeferredPromise<T>()
|
||||
const push = (task: Callback<T>) => {
|
||||
let taskPromise = new DeferredPromise<T>()
|
||||
if (dedupeConcurrent) {
|
||||
queue = []
|
||||
if (nextPromise.started) nextPromise = new DeferredPromise<T>()
|
||||
taskPromise = nextPromise
|
||||
}
|
||||
queue.push(() => {
|
||||
taskPromise.started = true
|
||||
task().then(taskPromise.resolve).catch(taskPromise.reject)
|
||||
return taskPromise.promise
|
||||
})
|
||||
if (!running) running = start()
|
||||
return taskPromise.promise
|
||||
}
|
||||
const start = async () => {
|
||||
while (queue.length) {
|
||||
const task = queue.shift()!
|
||||
await task().catch(() => {})
|
||||
}
|
||||
running = undefined
|
||||
}
|
||||
return {
|
||||
push,
|
||||
flush: () => running || Promise.resolve(),
|
||||
get size() {
|
||||
return queue.length
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export const createAsyncQueues = <T = void>(opts = { dedupeConcurrent: false }) => {
|
||||
const queues: { [queueId: string]: AsyncQueue<T> } = {}
|
||||
const push = (queueId: string, task: Callback<T>) => {
|
||||
if (!queues[queueId]) queues[queueId] = createAsyncQueue<T>(opts)
|
||||
return queues[queueId].push(task)
|
||||
}
|
||||
const flush = (queueId: string) => {
|
||||
if (!queues[queueId]) queues[queueId] = createAsyncQueue<T>(opts)
|
||||
return queues[queueId].flush()
|
||||
}
|
||||
return { push, flush }
|
||||
}
|
||||
|
||||
class DeferredPromise<T = void, E = any> {
|
||||
started = false
|
||||
resolve: (x: T | PromiseLike<T>) => void = () => {}
|
||||
reject: (x: E) => void = () => {}
|
||||
promise: Promise<T>
|
||||
|
||||
constructor() {
|
||||
this.promise = new Promise<T>((res, rej) => {
|
||||
this.resolve = res
|
||||
this.reject = rej
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// function main() {
|
||||
// const queue = createAsyncQueue()
|
||||
// queue.push(async () => {
|
||||
// console.log(0)
|
||||
// }) // returns 0
|
||||
// queue.push(async () => {
|
||||
// console.log(1)
|
||||
|
||||
// return new Promise((resolve, reject) => {
|
||||
// setTimeout(() => {
|
||||
// console.log('12')
|
||||
// resolve()
|
||||
// }, 1000)
|
||||
// })
|
||||
// }) // returns 3
|
||||
// queue.push(async () => console.log(2)) // returns 3
|
||||
// queue.push(async () => console.log(3)) // returns 3
|
||||
// console.log('hi')
|
||||
// }
|
||||
|
||||
// main()
|
@ -221,11 +221,15 @@ export const JC_CONTRACTS = {
|
||||
evolveFactory: "0x9e6167B11Ad15D8407865E21D4770E9F6CF10853",
|
||||
minterFactory: "0xb60c7312F56da4303CE3bf27124f1850dBe1D0E5",
|
||||
chipLocker: "0x4Ef766854EE104053cF2D243620b7A643fCC2B54",
|
||||
nftFactory: "0xEA374dC9f94E7A3A2eE8C0C910954cE15E2C469E", // for minterFactory call
|
||||
market: "0x806eA3301c2bA2a3C710D97931a6C0Fe00E45B33",
|
||||
},
|
||||
1338: {
|
||||
nftMall: "0x5017A545b09ab9a30499DE7F431DF0855bCb7275",
|
||||
evolveFactory: "0xaD888d0Ade988EbEe74B8D4F39BF29a8d0fe8A8D",
|
||||
minterFactory: "0x6eD79Aa1c71FD7BdBC515EfdA3Bd4e26394435cC",
|
||||
chipLocker: "0xFF6049B87215476aBf744eaA3a476cBAd46fB1cA",
|
||||
nftFactory: "0xA94B7f0465E98609391C623d0560C5720a3f2D33", // for minterFactory call
|
||||
market: "0xFC628dd79137395F3C9744e33b1c5DE554D94882",
|
||||
},
|
||||
};
|
||||
|
@ -5,3 +5,9 @@ export const WALLET_API_HOST = "https://wallet.cebggame.com";
|
||||
export const MAX_TRY_COUNT = 6;
|
||||
|
||||
export const MAX_UPLOAD_COUNT = 10;
|
||||
|
||||
export const TX_CONFIRM_BLOCKS = 6;
|
||||
|
||||
export const NATIVE_PK_PREFIX = "0x000000000000000000000000";
|
||||
|
||||
export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
||||
|
82
src/index.ts
82
src/index.ts
@ -1,37 +1,47 @@
|
||||
import { singleton } from "./decorator/singleton.decorator";
|
||||
import Web3 from "web3";
|
||||
import {
|
||||
recoverTypedSignature,
|
||||
signTypedData,
|
||||
SignTypedDataVersion,
|
||||
} from "@metamask/eth-sig-util";
|
||||
import Web3 from "web3";
|
||||
import "whatwg-fetch";
|
||||
import { AllChains } from "./data/allchain";
|
||||
import {
|
||||
createWalletEvents,
|
||||
WALLET_ACCOUNT_CHANGE,
|
||||
WALLET_CHAIN_CHANGE,
|
||||
WALLET_TOKEN_TYPE_CHANGE,
|
||||
} from "./common/WalletEvent";
|
||||
import { ERC20Standard } from "./standards/ERC20Standard";
|
||||
import { ERC721Standard } from "./standards/ERC721Standard";
|
||||
import { IAccount, INFT, initAccount, initNFT } from "./data/DataModel";
|
||||
import { loadToken, saveData } from "./manage/DataManage";
|
||||
import { WALLET_STORAGE_KEY_NAME } from "./config/constants";
|
||||
import { JazzIcon } from "./comp/JazzIcon";
|
||||
import { ZWalletConnect } from "./comp/ZWalletConnect";
|
||||
import { DEFALUT_TOKENS } from "./config/chain_config";
|
||||
import {
|
||||
NATIVE_PK_PREFIX,
|
||||
TX_CONFIRM_BLOCKS,
|
||||
WALLET_STORAGE_KEY_NAME,
|
||||
} from "./config/constants";
|
||||
import { AllChains } from "./data/allchain";
|
||||
import { IAccount, INFT, initAccount, initNFT } from "./data/DataModel";
|
||||
import { singleton } from "./decorator/singleton.decorator";
|
||||
import { saveData } from "./manage/DataManage";
|
||||
import {
|
||||
loadInternalWallet,
|
||||
restoreWalletByMnemonic,
|
||||
} from "./manage/WalletManage";
|
||||
import { buildLoginSignMsg, signLogin } from "./util/sign.util";
|
||||
import { JazzIcon } from "./comp/JazzIcon";
|
||||
import { ERC1155Standard } from "./standards/ERC1155Standard";
|
||||
import { ZWalletConnect } from "./comp/ZWalletConnect";
|
||||
import { getJCErc721Info, getTypeByAddress, UNKNOW } from "./util/chain.util";
|
||||
import { JCStandard } from "./standards/JCStandard";
|
||||
import { NativeSvr } from "./services/NativeSvr";
|
||||
import { TranHistorySvr } from "./services/TranHistorySvr";
|
||||
import { ChainCommon } from "./standards/ChainCommon";
|
||||
import { ERC1155Standard } from "./standards/ERC1155Standard";
|
||||
import { ERC20Standard } from "./standards/ERC20Standard";
|
||||
import { ERC721Standard } from "./standards/ERC721Standard";
|
||||
import { JCStandard } from "./standards/JCStandard";
|
||||
import {
|
||||
getJCErc721Info,
|
||||
getTypeByAddress,
|
||||
universalChainCb,
|
||||
UNKNOW,
|
||||
} from "./util/chain.util";
|
||||
import { fromTokenMinimalUnit } from "./util/number.util";
|
||||
import { buildLoginSignMsg, signLogin } from "./util/sign.util";
|
||||
|
||||
var global =
|
||||
(typeof globalThis !== "undefined" && globalThis) ||
|
||||
@ -69,6 +79,7 @@ export default class JCWallet {
|
||||
public chainCommon: ChainCommon;
|
||||
public jcStandard: JCStandard;
|
||||
public nativeSvr: NativeSvr;
|
||||
public historySvr: TranHistorySvr;
|
||||
public wConnect: ZWalletConnect;
|
||||
public mainHandlers = createWalletEvents();
|
||||
public data: IAccount[] = [];
|
||||
@ -78,9 +89,11 @@ export default class JCWallet {
|
||||
private rpcUrl: string = "";
|
||||
public rpc: any = {};
|
||||
public nativeAccount = "";
|
||||
public feeAddressMap: Map<string, string> = new Map();
|
||||
|
||||
constructor({ type, chain }: { type: number; chain: number }) {
|
||||
this.nativeSvr = new NativeSvr();
|
||||
this.historySvr = new TranHistorySvr();
|
||||
this.walletType = type;
|
||||
chain = chain || 80001;
|
||||
let data = AllChains.find((o) => o.id === chain);
|
||||
@ -105,6 +118,7 @@ export default class JCWallet {
|
||||
console.log("native wallet address: " + address);
|
||||
var start = Date.now();
|
||||
this.web3 = new Web3(this.rpcUrl);
|
||||
this.web3.eth.transactionConfirmationBlocks = TX_CONFIRM_BLOCKS;
|
||||
console.log(`init web3 cost: ${(Date.now() - start) / 1000}`);
|
||||
this.erc20Standard = new ERC20Standard(this.web3);
|
||||
console.log("init Erc20Standard");
|
||||
@ -310,8 +324,9 @@ export default class JCWallet {
|
||||
// let account = this.web3.eth.accounts.create()
|
||||
this.wallet = this.web3.eth.accounts.wallet;
|
||||
const index = this.getMaxIdexOfType(0);
|
||||
const nativePrefix = "0x000000000000000000000000";
|
||||
const nativePrivateKey = `${nativePrefix}${this.currentAccAddr.slice(2)}`;
|
||||
const nativePrivateKey = `${NATIVE_PK_PREFIX}${this.currentAccAddr.slice(
|
||||
2
|
||||
)}`;
|
||||
const acc = this.web3.eth.accounts.privateKeyToAccount(nativePrivateKey);
|
||||
const account = this.wallet.add(acc);
|
||||
this.web3.eth.defaultAccount = account.address;
|
||||
@ -411,12 +426,26 @@ export default class JCWallet {
|
||||
if (estimate) {
|
||||
return this.generateGasShow(gas);
|
||||
}
|
||||
return this.web3.eth.sendTransaction({
|
||||
const reqData = {
|
||||
from,
|
||||
to,
|
||||
gas,
|
||||
value: amountToSend,
|
||||
});
|
||||
};
|
||||
const logData = {
|
||||
gas,
|
||||
title: "transfer",
|
||||
details: [
|
||||
{
|
||||
address: "eth",
|
||||
from,
|
||||
to,
|
||||
value: amountToSend,
|
||||
id: "0",
|
||||
},
|
||||
],
|
||||
};
|
||||
return universalChainCb(logData, this.web3.eth.sendTransaction(reqData));
|
||||
}
|
||||
|
||||
public async getBalance(account?: string) {
|
||||
@ -619,6 +648,19 @@ export default class JCWallet {
|
||||
estimate,
|
||||
});
|
||||
}
|
||||
|
||||
public async getFeeAddress(typeName: string) {
|
||||
if (!this.feeAddressMap.has(typeName)) {
|
||||
const address = await this.jcStandard.fetchFeeToAddress(
|
||||
this.currentChain.id,
|
||||
typeName
|
||||
);
|
||||
if (address) {
|
||||
this.feeAddressMap.set(typeName, address);
|
||||
}
|
||||
}
|
||||
return this.feeAddressMap.get(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
// window.jc = window.jc || {wallet: new JCWallet()};
|
||||
@ -626,7 +668,7 @@ export default class JCWallet {
|
||||
export * from "./common/WalletEvent";
|
||||
export * from "./common/ZError";
|
||||
export * from "./config/chain_config";
|
||||
export * from "./util/number.util";
|
||||
export * from "./util/wallet.util";
|
||||
export * from "./data/DataModel";
|
||||
export * from "./lib/WalletConnect";
|
||||
export * from "./util/number.util";
|
||||
export * from "./util/wallet.util";
|
||||
|
@ -37,11 +37,39 @@ export async function POST(url, data) {
|
||||
return request(url, option);
|
||||
}
|
||||
|
||||
export async function DELETE(url, data) {
|
||||
let option = {
|
||||
method: "DELETE",
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
return request(url, option);
|
||||
}
|
||||
|
||||
export async function PUT(url, data) {
|
||||
let option = {
|
||||
method: "PUT",
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
return request(url, option);
|
||||
}
|
||||
|
||||
export async function POST_JSON(url, data) {
|
||||
return POST(url, data).then((res) => {
|
||||
return res.json();
|
||||
});
|
||||
}
|
||||
|
||||
export async function DELETE_JSON(url, data) {
|
||||
return DELETE(url, data).then((res) => {
|
||||
return res.json();
|
||||
});
|
||||
}
|
||||
|
||||
export async function PUT_JSON(url, data) {
|
||||
return PUT(url, data).then((res) => {
|
||||
return res.json();
|
||||
});
|
||||
}
|
||||
/**
|
||||
* var headers = new Headers();
|
||||
headers.append("Content-Type", "application/json");
|
||||
|
23
src/queue/record.queue.ts
Normal file
23
src/queue/record.queue.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { saveRecord } from "../api/RecordApi";
|
||||
import { AsyncQueue, createAsyncQueue } from "../common/AsyncQueue";
|
||||
import { singleton } from "../decorator/singleton.decorator";
|
||||
|
||||
@singleton
|
||||
export class LoggerQueue {
|
||||
private queue: AsyncQueue;
|
||||
|
||||
constructor() {
|
||||
this.queue = createAsyncQueue();
|
||||
}
|
||||
|
||||
public addLog(data: any) {
|
||||
this.queue.push(async () => {
|
||||
try {
|
||||
await saveRecord(data);
|
||||
} catch (err) {
|
||||
console.log("error save tx record: ");
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
43
src/services/TranHistorySvr.ts
Normal file
43
src/services/TranHistorySvr.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { records } from "../api/RecordApi";
|
||||
import { singleton } from "../decorator/singleton.decorator";
|
||||
|
||||
@singleton
|
||||
export class TranHistorySvr {
|
||||
/**
|
||||
* eth history
|
||||
*/
|
||||
public async ethRecords(start: number, limit: number) {
|
||||
start = start | 0;
|
||||
limit = limit | 0;
|
||||
const data = { start, limit, chain: jc.wallet.currentChain.id };
|
||||
return records(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* token history
|
||||
*/
|
||||
public async tokenRecords({
|
||||
address,
|
||||
tokenId,
|
||||
start,
|
||||
limit,
|
||||
}: {
|
||||
address: string;
|
||||
tokenId?: string;
|
||||
start: number;
|
||||
limit: number;
|
||||
}) {
|
||||
start = start | 0;
|
||||
limit = limit | 0;
|
||||
const data: any = {
|
||||
start,
|
||||
limit,
|
||||
chain: jc.wallet.currentChain.id,
|
||||
"details.address": address,
|
||||
};
|
||||
if (tokenId) {
|
||||
data["details.id"] = tokenId + "";
|
||||
}
|
||||
return records(data);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import Web3 from "web3";
|
||||
import { abiERC1155 } from "../abis/abiERC1155";
|
||||
import { universalChainCb } from "../util/chain.util";
|
||||
import { timeoutFetch } from "../util/net.util";
|
||||
import { getFormattedIpfsUrl } from "../util/wallet.util";
|
||||
|
||||
@ -110,45 +111,6 @@ export class ERC1155Standard {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Transfer single ERC1155 token.
|
||||
* When minting/creating tokens, the from arg MUST be set to 0x0 (i.e. zero address).
|
||||
* When burning/destroying tokens, the to arg MUST be set to 0x0 (i.e. zero address).
|
||||
*
|
||||
* @param operator - ERC1155 token address.
|
||||
* @param from - ERC1155 token holder.
|
||||
* @param to - ERC1155 token recipient.
|
||||
* @param id - ERC1155 token id.
|
||||
* @param value - Number of tokens to be sent.
|
||||
* @returns Promise resolving to the 'transferSingle'.
|
||||
*/
|
||||
transferSingle = async (
|
||||
operator: string,
|
||||
from: string,
|
||||
to: string,
|
||||
id: string,
|
||||
value: string
|
||||
): Promise<void> => {
|
||||
const contract = new this.web3.eth.Contract(abiERC1155, operator);
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
contract.methods.transferSingle(
|
||||
operator,
|
||||
from,
|
||||
to,
|
||||
id,
|
||||
value,
|
||||
(error: Error, result: void) => {
|
||||
/* istanbul ignore if */
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Query if a contract implements an interface.
|
||||
*
|
||||
@ -246,18 +208,36 @@ export class ERC1155Standard {
|
||||
const contract = new this.web3.eth.Contract(abiERC1155, address);
|
||||
if (!gas) {
|
||||
gas = await contract.methods
|
||||
.safeBatchTransferFrom(from, to, tokenIds, amounts, "")
|
||||
.safeBatchTransferFrom(from, to, tokenIds, amounts, [])
|
||||
.estimateGas({ gas: 1000000 });
|
||||
}
|
||||
gas = (gas * 1.1) | 1;
|
||||
if (estimate) {
|
||||
return jc.wallet.generateGasShow(gas);
|
||||
}
|
||||
return contract.methods
|
||||
.safeBatchTransferFrom(from, to, tokenIds, amounts, "")
|
||||
const detailArr = [];
|
||||
for (let i = 0, l = tokenIds.length; i < l; i++) {
|
||||
detailArr.push({
|
||||
address,
|
||||
from,
|
||||
to,
|
||||
id: tokenIds[i],
|
||||
amount: amounts[i],
|
||||
});
|
||||
}
|
||||
const logData = {
|
||||
gas,
|
||||
title: "transfer",
|
||||
details: detailArr,
|
||||
};
|
||||
return universalChainCb(
|
||||
logData,
|
||||
contract.methods
|
||||
.safeBatchTransferFrom(from, to, tokenIds, amounts, [])
|
||||
.send({
|
||||
from,
|
||||
gas,
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import Web3 from "web3";
|
||||
import { abiERC20 } from "../abis/abiERC20";
|
||||
import { BN, toUtf8 } from "ethereumjs-util";
|
||||
import { universalChainCb } from "../util/chain.util";
|
||||
|
||||
export class ERC20Standard {
|
||||
private web3: Web3;
|
||||
@ -166,9 +167,25 @@ export class ERC20Standard {
|
||||
if (estimate) {
|
||||
return jc.wallet.generateGasShow(gas);
|
||||
}
|
||||
return contract.methods.transfer(to, amountBN).send({
|
||||
const logData = {
|
||||
gas,
|
||||
title: "transfer",
|
||||
details: [
|
||||
{
|
||||
address,
|
||||
from,
|
||||
to,
|
||||
value: amountBN,
|
||||
id: "0",
|
||||
},
|
||||
],
|
||||
};
|
||||
return universalChainCb(
|
||||
logData,
|
||||
contract.methods.transfer(to, amountBN).send({
|
||||
from,
|
||||
gas,
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Web3 from "web3";
|
||||
import { abiERC721 } from "../abis/abiERC721";
|
||||
import { universalChainCb } from "../util/chain.util";
|
||||
import { timeoutFetch } from "../util/net.util";
|
||||
import { getFormattedIpfsUrl } from "../util/wallet.util";
|
||||
|
||||
@ -311,9 +312,24 @@ export class ERC721Standard {
|
||||
if (estimate) {
|
||||
return jc.wallet.generateGasShow(gas);
|
||||
}
|
||||
return contract.methods.safeTransferFrom(from, to, tokenId).send({
|
||||
const logData = {
|
||||
gas,
|
||||
title: "transfer",
|
||||
details: [
|
||||
{
|
||||
address,
|
||||
from,
|
||||
to,
|
||||
id: tokenId,
|
||||
},
|
||||
],
|
||||
};
|
||||
return universalChainCb(
|
||||
logData,
|
||||
contract.methods.safeTransferFrom(from, to, tokenId).send({
|
||||
from,
|
||||
gas,
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import assert from "assert";
|
||||
import Web3 from "web3";
|
||||
import { abiNftMall } from "../abis/abiBENftMall";
|
||||
import { abiChipLocker } from "../abis/abiChipLocker";
|
||||
@ -5,6 +6,8 @@ import { abiERC1155 } from "../abis/abiERC1155";
|
||||
import { abiEvolveFactory } from "../abis/abiUserEvolveFactory";
|
||||
import { abiMinterFactory } from "../abis/abiUserMinterFactory";
|
||||
import { JC_CONTRACTS } from "../config/chain_config";
|
||||
import { ZERO_ADDRESS } from "../config/constants";
|
||||
import { getAddressByType, universalChainCb } from "../util/chain.util";
|
||||
import { SAMPLE_GAS } from "./ChainCommon";
|
||||
|
||||
export class JCStandard {
|
||||
@ -59,9 +62,32 @@ export class JCStandard {
|
||||
jumpToWallet();
|
||||
}, 1500);
|
||||
}
|
||||
return contract.methods
|
||||
.buy721NFT(addresses, values, signature)
|
||||
.send({ gas });
|
||||
const details = [];
|
||||
// payment token
|
||||
const feeAddress = await jc.wallet.getFeeAddress("nftMall");
|
||||
details.push({
|
||||
address: addresses[2],
|
||||
from: jc.wallet.currentAccAddr,
|
||||
to: feeAddress,
|
||||
value: values[1],
|
||||
});
|
||||
// nft minted
|
||||
details.push({
|
||||
address: addresses[1],
|
||||
from: ZERO_ADDRESS,
|
||||
to: jc.wallet.currentAccAddr,
|
||||
id: values[0],
|
||||
});
|
||||
|
||||
const logData = {
|
||||
gas,
|
||||
title: "buy_erc721",
|
||||
details,
|
||||
};
|
||||
return universalChainCb(
|
||||
logData,
|
||||
contract.methods.buy721NFT(addresses, values, signature).send({ gas })
|
||||
);
|
||||
}
|
||||
|
||||
async buyNft1155({
|
||||
@ -113,9 +139,37 @@ export class JCStandard {
|
||||
jumpToWallet();
|
||||
}, 1500);
|
||||
}
|
||||
return contract.methods
|
||||
const details = [];
|
||||
// payment token
|
||||
const feeAddress = await jc.wallet.getFeeAddress("nftMall");
|
||||
details.push({
|
||||
address: addresses[2],
|
||||
from: jc.wallet.currentAccAddr,
|
||||
to: feeAddress, // can't fetch address in contract, use seller instead
|
||||
value: values[0],
|
||||
});
|
||||
// 1155 token minted
|
||||
for (let i = 0, l = ids.length; i < l; i++) {
|
||||
details.push({
|
||||
address: addresses[1],
|
||||
from: ZERO_ADDRESS,
|
||||
to: jc.wallet.currentAccAddr,
|
||||
id: ids[i],
|
||||
value: amounts[i],
|
||||
});
|
||||
}
|
||||
|
||||
const logData = {
|
||||
gas,
|
||||
title: "buy_erc1155",
|
||||
details,
|
||||
};
|
||||
return universalChainCb(
|
||||
logData,
|
||||
contract.methods
|
||||
.buy1155NFT(addresses, values, ids, amounts, signature)
|
||||
.send({ gas });
|
||||
.send({ gas })
|
||||
);
|
||||
}
|
||||
|
||||
async evolve721NFT({
|
||||
@ -167,9 +221,32 @@ export class JCStandard {
|
||||
jumpToWallet();
|
||||
}, 1500);
|
||||
}
|
||||
return contract.methods
|
||||
const details = [];
|
||||
// nft evolved
|
||||
details.push({
|
||||
address: nftAddress,
|
||||
from: jc.wallet.currentAccAddr,
|
||||
to: jc.wallet.currentAccAddr,
|
||||
id: tokenIds[0],
|
||||
});
|
||||
// nft burn
|
||||
details.push({
|
||||
address: nftAddress,
|
||||
from: jc.wallet.currentAccAddr,
|
||||
to: ZERO_ADDRESS,
|
||||
id: tokenIds[1],
|
||||
});
|
||||
const logData = {
|
||||
gas,
|
||||
title: "evolve_721",
|
||||
details,
|
||||
};
|
||||
return universalChainCb(
|
||||
logData,
|
||||
contract.methods
|
||||
.evolve721NFT(nftAddress, tokenIds, startTime, nonce, signature)
|
||||
.send({ gas });
|
||||
.send({ gas })
|
||||
);
|
||||
}
|
||||
|
||||
async evolveChip({
|
||||
@ -219,9 +296,39 @@ export class JCStandard {
|
||||
jumpToWallet();
|
||||
}, 1500);
|
||||
}
|
||||
return contract.methods
|
||||
const details = [];
|
||||
const chipAddress = getAddressByType("chip");
|
||||
assert(!!chipAddress, "chip address not found");
|
||||
// chip evolved
|
||||
details.push({
|
||||
address: chipAddress,
|
||||
from: jc.wallet.currentAccAddr,
|
||||
to: jc.wallet.currentAccAddr,
|
||||
id: tokenIds[0],
|
||||
value: 1,
|
||||
});
|
||||
// chip burn
|
||||
for (let i = 1, l = tokenIds.length; i < l; i++) {
|
||||
details.push({
|
||||
address: chipAddress,
|
||||
from: jc.wallet.currentAccAddr,
|
||||
to: ZERO_ADDRESS,
|
||||
id: tokenIds[i],
|
||||
value: 1,
|
||||
});
|
||||
}
|
||||
|
||||
const logData = {
|
||||
gas,
|
||||
title: "evolve_chip",
|
||||
details,
|
||||
};
|
||||
return universalChainCb(
|
||||
logData,
|
||||
contract.methods
|
||||
.evolveChip(tokenIds, startTime, nonce, signature)
|
||||
.send({ gas });
|
||||
.send({ gas })
|
||||
);
|
||||
}
|
||||
|
||||
async mintShardBatchUser({
|
||||
@ -273,9 +380,31 @@ export class JCStandard {
|
||||
jumpToWallet();
|
||||
}, 1500);
|
||||
}
|
||||
return contract.methods
|
||||
const details = [];
|
||||
const shardAddress = getAddressByType("shard");
|
||||
assert(!!shardAddress, "shard address not found");
|
||||
// shard
|
||||
for (let i = 0, l = tokenIds.length; i < l; i++) {
|
||||
details.push({
|
||||
address: shardAddress,
|
||||
from: ZERO_ADDRESS,
|
||||
to: jc.wallet.currentAccAddr,
|
||||
id: tokenIds[i],
|
||||
value: amounts[i],
|
||||
});
|
||||
}
|
||||
|
||||
const logData = {
|
||||
gas,
|
||||
title: "mint_shard",
|
||||
details,
|
||||
};
|
||||
return universalChainCb(
|
||||
logData,
|
||||
contract.methods
|
||||
.mintShardBatchUser(tokenIds, amounts, startTime, nonce, signature)
|
||||
.send({ gas });
|
||||
.send({ gas })
|
||||
);
|
||||
}
|
||||
|
||||
async shardMixByUser({
|
||||
@ -310,7 +439,7 @@ export class JCStandard {
|
||||
});
|
||||
if (!gas) {
|
||||
try {
|
||||
let gas = await contract.methods
|
||||
gas = await contract.methods
|
||||
.shardMixByUser(
|
||||
tokenId,
|
||||
nftType,
|
||||
@ -346,7 +475,47 @@ export class JCStandard {
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
return contract.methods
|
||||
const details = [];
|
||||
const shardAddress = getAddressByType("shard");
|
||||
assert(!!shardAddress, "shard address not found");
|
||||
// nft mint
|
||||
const nftTypeName = nftType === 0 ? "hero" : "weapon";
|
||||
const nftAddress = getAddressByType(nftTypeName);
|
||||
assert(!!nftAddress, "nft address not found");
|
||||
details.push({
|
||||
address: nftAddress,
|
||||
from: ZERO_ADDRESS,
|
||||
to: jc.wallet.currentAccAddr,
|
||||
id: tokenId,
|
||||
value: 1,
|
||||
});
|
||||
// payment token
|
||||
const feeAddress = await jc.wallet.getFeeAddress("nftFactory");
|
||||
details.push({
|
||||
address: payToken,
|
||||
from: jc.wallet.currentAccAddr,
|
||||
to: feeAddress,
|
||||
value: payAmount,
|
||||
});
|
||||
// shard burn
|
||||
for (let i = 0, l = ids.length; i < l; i++) {
|
||||
details.push({
|
||||
address: shardAddress,
|
||||
from: jc.wallet.currentAccAddr,
|
||||
to: ZERO_ADDRESS,
|
||||
id: ids[i],
|
||||
value: amounts[i],
|
||||
});
|
||||
}
|
||||
|
||||
const logData = {
|
||||
gas,
|
||||
title: "shard_mix",
|
||||
details,
|
||||
};
|
||||
return universalChainCb(
|
||||
logData,
|
||||
contract.methods
|
||||
.shardMixByUser(
|
||||
tokenId,
|
||||
nftType,
|
||||
@ -358,7 +527,8 @@ export class JCStandard {
|
||||
nonce,
|
||||
signature
|
||||
)
|
||||
.send({ gas });
|
||||
.send({ gas })
|
||||
);
|
||||
}
|
||||
|
||||
async pluginChip({
|
||||
@ -438,9 +608,36 @@ export class JCStandard {
|
||||
jumpToWallet();
|
||||
}, 1500);
|
||||
}
|
||||
return await contract.methods
|
||||
const details = [];
|
||||
// target nft
|
||||
details.push({
|
||||
address: addresses[0],
|
||||
from: jc.wallet.currentAccAddr,
|
||||
to: jc.wallet.currentAccAddr,
|
||||
id: values[0],
|
||||
});
|
||||
// chip plugin
|
||||
for (let i = 0, l = chipIds.length; i < l; i++) {
|
||||
details.push({
|
||||
address: addresses[1],
|
||||
from: jc.wallet.currentAccAddr,
|
||||
to: lockerAddress,
|
||||
id: chipIds[i],
|
||||
value: 1,
|
||||
});
|
||||
}
|
||||
|
||||
const logData = {
|
||||
gas,
|
||||
title: "plug_chip",
|
||||
details,
|
||||
};
|
||||
return universalChainCb(
|
||||
logData,
|
||||
contract.methods
|
||||
.pluginChip(addresses, values, chipIds, slots, signature)
|
||||
.send({ gas: gas0 });
|
||||
.send({ gas })
|
||||
);
|
||||
}
|
||||
|
||||
async unplugChip({
|
||||
@ -460,8 +657,7 @@ export class JCStandard {
|
||||
gas?: number;
|
||||
estimate: number;
|
||||
}) {
|
||||
let lockerAddress =
|
||||
JC_CONTRACTS[window.jc.wallet.currentChain.id].chipLocker;
|
||||
let lockerAddress = JC_CONTRACTS[jc.wallet.currentChain.id].chipLocker;
|
||||
const contract = new this.web3.eth.Contract(abiChipLocker, lockerAddress, {
|
||||
from: jc.wallet.currentAccAddr,
|
||||
});
|
||||
@ -491,8 +687,44 @@ export class JCStandard {
|
||||
jumpToWallet();
|
||||
}, 1500);
|
||||
}
|
||||
return await contract.methods
|
||||
const details = [];
|
||||
// target nft
|
||||
details.push({
|
||||
address: addresses[0],
|
||||
from: jc.wallet.currentAccAddr,
|
||||
to: jc.wallet.currentAccAddr,
|
||||
id: values[0],
|
||||
});
|
||||
// chip plugin
|
||||
for (let i = 0, l = chipIds.length; i < l; i++) {
|
||||
details.push({
|
||||
address: addresses[1],
|
||||
from: lockerAddress,
|
||||
to: jc.wallet.currentAccAddr,
|
||||
id: chipIds[i],
|
||||
value: 1,
|
||||
});
|
||||
}
|
||||
|
||||
const logData = {
|
||||
gas,
|
||||
title: "unplug_chip",
|
||||
details,
|
||||
};
|
||||
return universalChainCb(
|
||||
logData,
|
||||
contract.methods
|
||||
.unplugChip(addresses, values, chipIds, slots, signature)
|
||||
.send({ gas });
|
||||
.send({ gas })
|
||||
);
|
||||
}
|
||||
|
||||
// fetch feeToAddress from contact
|
||||
async fetchFeeToAddress(chain: number, typeName: string) {
|
||||
// jc.wallet.currentChain.id
|
||||
let address = JC_CONTRACTS[chain][typeName];
|
||||
assert(address, "address not found");
|
||||
const contract = new this.web3.eth.Contract(abiChipLocker, address);
|
||||
return contract.methods.feeToAddress().call();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
import { BASE_TOKEN_URI, DEFAULT_NFT_TYPES } from "../config/chain_config";
|
||||
import { TX_CONFIRM_BLOCKS } from "../config/constants";
|
||||
import { LoggerQueue } from "../queue/record.queue";
|
||||
import { toBN } from "web3-utils";
|
||||
|
||||
export const UNKNOW = 'unknow';
|
||||
export const UNKNOW = "unknow";
|
||||
|
||||
/**
|
||||
* change price with customer decimals to bigNum with 18 decimals
|
||||
@ -9,8 +12,8 @@ export const UNKNOW = 'unknow';
|
||||
* @return {string}
|
||||
*/
|
||||
export function parsePrice(price: number, decimals: number) {
|
||||
const n = 19 - decimals
|
||||
return price + new Array(n).join('0')
|
||||
const n = 19 - decimals;
|
||||
return price + new Array(n).join("0");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -20,21 +23,25 @@ export function parsePrice(price: number, decimals: number) {
|
||||
* @param {number} fixed
|
||||
* @return {number | string}
|
||||
*/
|
||||
export function formatPrice(price: number|string, decimals?: number, fixed = 2) {
|
||||
export function formatPrice(
|
||||
price: number | string,
|
||||
decimals?: number,
|
||||
fixed = 2
|
||||
) {
|
||||
if (!decimals) {
|
||||
return price
|
||||
return price;
|
||||
}
|
||||
let str = price + ''
|
||||
const length = str.length
|
||||
str = str.padStart(decimals, '0')
|
||||
let str = price + "";
|
||||
const length = str.length;
|
||||
str = str.padStart(decimals, "0");
|
||||
if (decimals >= length) {
|
||||
str = '0.' + str
|
||||
str = "0." + str;
|
||||
} else {
|
||||
const pos = length - decimals
|
||||
str = str.slice(0, pos) + '.' + str.slice(pos)
|
||||
const pos = length - decimals;
|
||||
str = str.slice(0, pos) + "." + str.slice(pos);
|
||||
}
|
||||
str = str.slice(0, str.lastIndexOf('.') + fixed + 1)
|
||||
return str
|
||||
str = str.slice(0, str.lastIndexOf(".") + fixed + 1);
|
||||
return str;
|
||||
// return str.replace(/0+$/, '').replace(/\.+$/, '')
|
||||
}
|
||||
|
||||
@ -44,26 +51,98 @@ export function formatPrice(price: number|string, decimals?: number, fixed = 2)
|
||||
* @return {string}
|
||||
*/
|
||||
export function toHexChainId(chainId: number) {
|
||||
return '0x' + chainId.toString(16)
|
||||
return "0x" + chainId.toString(16);
|
||||
}
|
||||
|
||||
|
||||
export function getTypeByAddress(chain: number, address: string) {
|
||||
const cfgs = DEFAULT_NFT_TYPES[chain];
|
||||
let categor = UNKNOW;
|
||||
let type: 'erc721' | 'erc1155' = 'erc721';
|
||||
let type: "erc721" | "erc1155" = "erc721";
|
||||
if (cfgs) {
|
||||
for (let key in cfgs) {
|
||||
if (cfgs[key] && cfgs[key].address === address) {
|
||||
categor = key
|
||||
type = cfgs[key].type
|
||||
categor = key;
|
||||
type = cfgs[key].type;
|
||||
}
|
||||
}
|
||||
}
|
||||
return { categor, type };
|
||||
}
|
||||
|
||||
export async function getJCErc721Info(tokenId: string) {
|
||||
const url = `${BASE_TOKEN_URI}${tokenId}`
|
||||
return fetch(url).then(response => {return response.json()})
|
||||
export function getAddressByType(typeName: string) {
|
||||
const cfgs = DEFAULT_NFT_TYPES[jc.wallet.currentChain.id];
|
||||
let address = "";
|
||||
if (cfgs) {
|
||||
if (cfgs[typeName]) {
|
||||
address = cfgs[typeName].address;
|
||||
}
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
export async function getJCErc721Info(tokenId: string) {
|
||||
const url = `${BASE_TOKEN_URI}${tokenId}`;
|
||||
return fetch(url).then((response) => {
|
||||
return response.json();
|
||||
});
|
||||
}
|
||||
|
||||
export function universalChainCb(reqData: any, req: any) {
|
||||
return req
|
||||
.on("presend", function (dataObj: any) {
|
||||
if (jc.wallet.isInternal) {
|
||||
console.log("before send tran: ", JSON.stringify(dataObj));
|
||||
let gasPrice;
|
||||
if (
|
||||
!dataObj.gasPrice &&
|
||||
dataObj.maxPriorityFeePerGas &&
|
||||
dataObj.maxFeePerGas
|
||||
) {
|
||||
gasPrice = toBN(dataObj.maxFeePerGas)
|
||||
.sub(toBN(dataObj.maxPriorityFeePerGas))
|
||||
.div(toBN(2))
|
||||
.mul(toBN(1000000000));
|
||||
} else if (dataObj.gasPrice) {
|
||||
gasPrice = toBN(dataObj.gasPrice);
|
||||
}
|
||||
reqData.gas = toBN(dataObj.gas).toString();
|
||||
reqData.gasPrice = gasPrice.toString();
|
||||
reqData.transactionHash = dataObj.transactionHash;
|
||||
reqData.chain = jc.wallet.currentChain.id;
|
||||
reqData.startTime = Date.now();
|
||||
new LoggerQueue().addLog(reqData);
|
||||
}
|
||||
})
|
||||
.on("transactionHash", function (hash: any) {
|
||||
console.log(`remote transactionHash: ${hash}`);
|
||||
})
|
||||
.on("confirmation", function (confirmationNumber, receipt) {
|
||||
console.log(
|
||||
`confirmation:: confirmationNumber: ${confirmationNumber} , receipt: ${receipt}`
|
||||
);
|
||||
if (jc.wallet.isInternal && confirmationNumber >= TX_CONFIRM_BLOCKS) {
|
||||
reqData.status = 2;
|
||||
reqData.confirmTime = Date.now();
|
||||
new LoggerQueue().addLog(reqData);
|
||||
}
|
||||
})
|
||||
.on("receipt", function (receipt) {
|
||||
console.log(receipt);
|
||||
if (jc.wallet.isInternal) {
|
||||
reqData.status = receipt.status ? 1 : 10;
|
||||
reqData.blockNumber = receipt.blockNumber;
|
||||
reqData.blockHash = receipt.blockHash;
|
||||
reqData.gas = receipt.gasUsed;
|
||||
new LoggerQueue().addLog(reqData);
|
||||
}
|
||||
return Promise.resolve(receipt);
|
||||
})
|
||||
.on("error", function (error, receipt) {
|
||||
console.log(error);
|
||||
if (jc.wallet.isInternal) {
|
||||
reqData.status = 11;
|
||||
new LoggerQueue().addLog(reqData);
|
||||
}
|
||||
return Promise.reject(error);
|
||||
});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user