@cityofzion/bs-neox 1.2.3 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import { INeo3NeoXBridgeService, TNeo3NeoXBridgeServiceBridgeParam,
|
|
1
|
+
import { INeo3NeoXBridgeService, TBridgeToken, TNeo3NeoXBridgeServiceBridgeParam, TNeo3NeoXBridgeServiceConstants, TNeo3NeoXBridgeServiceGetApprovalParam, TNeo3NeoXBridgeServiceGetNonceParams, TNeo3NeoXBridgeServiceGetTransactionHashByNonceParams } from '@cityofzion/blockchain-service';
|
|
2
2
|
import { BSNeoX } from '../../BSNeoX';
|
|
3
3
|
export declare class Neo3NeoXBridgeService<BSName extends string> implements INeo3NeoXBridgeService<BSName> {
|
|
4
4
|
#private;
|
|
5
5
|
readonly BRIDGE_SCRIPT_HASH = "0x1212000000000000000000000000000000000004";
|
|
6
|
-
readonly
|
|
7
|
-
|
|
8
|
-
readonly BRIDGE_NEO_BRIDGE_TRANSACTION_FEE = 0.008;
|
|
9
|
-
readonly BRIDGE_NEO3_NEO_TOKEN_HASH = "0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5";
|
|
6
|
+
readonly BRIDGE_BASE_CONFIRMATION_URL = "https://xexplorer.neo.org:8877/api/v1/transactions/deposits";
|
|
7
|
+
tokens: TBridgeToken[];
|
|
10
8
|
constructor(service: BSNeoX<BSName>);
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
getBridgeConstants(token: TBridgeToken): Promise<TNeo3NeoXBridgeServiceConstants>;
|
|
10
|
+
getApprovalFee(params: TNeo3NeoXBridgeServiceGetApprovalParam<BSName>): Promise<string>;
|
|
13
11
|
bridge(params: TNeo3NeoXBridgeServiceBridgeParam<BSName>): Promise<string>;
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
getNonce(params: TNeo3NeoXBridgeServiceGetNonceParams): Promise<string | null>;
|
|
13
|
+
getTransactionHashByNonce(params: TNeo3NeoXBridgeServiceGetTransactionHashByNonceParams): Promise<string | null>;
|
|
16
14
|
}
|
|
@@ -22,7 +22,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
22
22
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
23
23
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
24
|
};
|
|
25
|
-
var _Neo3NeoXBridgeService_instances, _Neo3NeoXBridgeService_service,
|
|
25
|
+
var _Neo3NeoXBridgeService_instances, _Neo3NeoXBridgeService_service, _Neo3NeoXBridgeService_buildApproveTransactionParam;
|
|
26
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
27
|
exports.Neo3NeoXBridgeService = void 0;
|
|
28
28
|
const blockchain_service_1 = require("@cityofzion/blockchain-service");
|
|
@@ -38,61 +38,62 @@ class Neo3NeoXBridgeService {
|
|
|
38
38
|
constructor(service) {
|
|
39
39
|
_Neo3NeoXBridgeService_instances.add(this);
|
|
40
40
|
this.BRIDGE_SCRIPT_HASH = '0x1212000000000000000000000000000000000004';
|
|
41
|
-
this.
|
|
42
|
-
this.BRIDGE_MIN_AMOUNT = 1;
|
|
43
|
-
this.BRIDGE_NEO_BRIDGE_TRANSACTION_FEE = 0.008;
|
|
44
|
-
this.BRIDGE_NEO3_NEO_TOKEN_HASH = '0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5';
|
|
41
|
+
this.BRIDGE_BASE_CONFIRMATION_URL = 'https://xexplorer.neo.org:8877/api/v1/transactions/deposits';
|
|
45
42
|
_Neo3NeoXBridgeService_service.set(this, void 0);
|
|
46
43
|
__classPrivateFieldSet(this, _Neo3NeoXBridgeService_service, service, "f");
|
|
44
|
+
this.tokens = [
|
|
45
|
+
Object.assign(Object.assign({}, BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET), { multichainId: 'gas' }),
|
|
46
|
+
Object.assign(Object.assign({}, BSNeoXConstants_1.BSNeoXConstants.NEO_TOKEN), { multichainId: 'neo' }),
|
|
47
|
+
];
|
|
47
48
|
}
|
|
48
|
-
|
|
49
|
+
getBridgeConstants(token) {
|
|
49
50
|
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
try {
|
|
52
|
+
const provider = new ethers_1.ethers.providers.JsonRpcProvider(__classPrivateFieldGet(this, _Neo3NeoXBridgeService_service, "f").network.url);
|
|
53
|
+
const bridgeContract = new ethers_1.ethers.Contract(this.BRIDGE_SCRIPT_HASH, bridge_1.BRIDGE_ABI, provider);
|
|
54
|
+
const isNativeToken = blockchain_service_1.BSTokenHelper.predicateByHash(token)(BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET);
|
|
55
|
+
const response = isNativeToken
|
|
56
|
+
? yield bridgeContract.nativeBridge()
|
|
57
|
+
: yield bridgeContract.tokenBridges(token.hash);
|
|
58
|
+
const bridgeFeeBn = blockchain_service_1.BSBigNumberHelper.fromDecimals(response.config.fee.toString(), BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET.decimals);
|
|
59
|
+
const minAmountBn = blockchain_service_1.BSBigNumberHelper.fromDecimals(response.config.minAmount.toString(), token.decimals);
|
|
60
|
+
const maxAmountBn = blockchain_service_1.BSBigNumberHelper.fromDecimals(response.config.maxAmount.toString(), token.decimals);
|
|
61
|
+
const bridgeFee = blockchain_service_1.BSBigNumberHelper.format(bridgeFeeBn, { decimals: BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET.decimals });
|
|
62
|
+
const bridgeMinAmount = blockchain_service_1.BSBigNumberHelper.format(minAmountBn, { decimals: token.decimals });
|
|
63
|
+
const bridgeMaxAmount = blockchain_service_1.BSBigNumberHelper.format(maxAmountBn, { decimals: token.decimals });
|
|
64
|
+
return {
|
|
65
|
+
bridgeFee,
|
|
66
|
+
bridgeMaxAmount,
|
|
67
|
+
bridgeMinAmount,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
throw new blockchain_service_1.BSError('Failed to get bridge constants', 'BRIDGE_CONSTANTS_ERROR', error);
|
|
56
72
|
}
|
|
57
|
-
const amountNumber = blockchain_service_1.BSBigNumberHelper.fromNumber(selectedTokenBalance.amount);
|
|
58
|
-
const receiveAmount = amountNumber.minus(this.BRIDGE_MIN_AMOUNT).toString();
|
|
59
|
-
const amount = amountNumber.toString();
|
|
60
|
-
const fee = yield this.calculateFee({
|
|
61
|
-
account,
|
|
62
|
-
receiverAddress,
|
|
63
|
-
validatedInputs: { receiveAmount, token, amount },
|
|
64
|
-
});
|
|
65
|
-
const maxAmount = amountNumber.minus(fee).toString();
|
|
66
|
-
return maxAmount;
|
|
67
73
|
});
|
|
68
74
|
}
|
|
69
|
-
|
|
75
|
+
getApprovalFee(params) {
|
|
70
76
|
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
-
if (!BSNeoXHelper_1.BSNeoXHelper.isMainnet(__classPrivateFieldGet(this, _Neo3NeoXBridgeService_service, "f").network))
|
|
72
|
-
throw new blockchain_service_1.BSError('Bridging to Neo3 is only supported on mainnet', 'UNSUPPORTED_NETWORK');
|
|
73
77
|
try {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const isGasToken = blockchain_service_1.BSTokenHelper.predicateByHash(params.validatedInputs.token)(BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET);
|
|
78
|
-
if (isGasToken) {
|
|
79
|
-
const estimated = yield signer.estimateGas(bridgeTransactionParam);
|
|
80
|
-
fee = gasPrice.mul(estimated);
|
|
78
|
+
const isNativeToken = blockchain_service_1.BSTokenHelper.predicateByHash(params.token)(BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET);
|
|
79
|
+
if (isNativeToken) {
|
|
80
|
+
throw new blockchain_service_1.BSError('No allowance fee for native token', 'NO_ALLOWANCE_FEE');
|
|
81
81
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
approvedEstimated = yield signer.estimateGas(approveTransactionParams);
|
|
86
|
-
}
|
|
87
|
-
// We can't estimate the gas for the bridge transaction because it requires the approve transaction to be done first
|
|
88
|
-
// if not the gas estimation of bridge transaction will fail so we add a fixed value
|
|
89
|
-
const neoBridgeFee = ethers_1.ethers.utils.parseUnits(this.BRIDGE_NEO_BRIDGE_TRANSACTION_FEE.toString(), BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET.decimals);
|
|
90
|
-
fee = gasPrice.mul(approvedEstimated).add(neoBridgeFee);
|
|
82
|
+
const populatedApproveTransaction = yield __classPrivateFieldGet(this, _Neo3NeoXBridgeService_instances, "m", _Neo3NeoXBridgeService_buildApproveTransactionParam).call(this, params);
|
|
83
|
+
if (!populatedApproveTransaction) {
|
|
84
|
+
throw new blockchain_service_1.BSError('Allowance is already sufficient', 'ALLOWANCE_ALREADY_SUFFICIENT');
|
|
91
85
|
}
|
|
92
|
-
|
|
86
|
+
const signer = yield __classPrivateFieldGet(this, _Neo3NeoXBridgeService_service, "f").generateSigner(params.account);
|
|
87
|
+
const approvedEstimated = yield signer.estimateGas(Object.assign(Object.assign({}, populatedApproveTransaction), { type: 2 }));
|
|
88
|
+
const provider = new ethers_1.ethers.providers.JsonRpcProvider(__classPrivateFieldGet(this, _Neo3NeoXBridgeService_service, "f").network.url);
|
|
89
|
+
const gasPrice = yield provider.getGasPrice();
|
|
90
|
+
return ethers_1.ethers.utils.formatEther(gasPrice.mul(approvedEstimated));
|
|
93
91
|
}
|
|
94
92
|
catch (error) {
|
|
95
|
-
|
|
93
|
+
if (error instanceof blockchain_service_1.BSError) {
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
throw new blockchain_service_1.BSError('Failed to get allowance fee', 'ALLOWANCE_FEE_ERROR', error);
|
|
96
97
|
}
|
|
97
98
|
});
|
|
98
99
|
}
|
|
@@ -102,10 +103,27 @@ class Neo3NeoXBridgeService {
|
|
|
102
103
|
throw new blockchain_service_1.BSError('Bridging to Neo3 is only supported on mainnet', 'UNSUPPORTED_NETWORK');
|
|
103
104
|
const { account } = params;
|
|
104
105
|
const signer = yield __classPrivateFieldGet(this, _Neo3NeoXBridgeService_service, "f").generateSigner(account);
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
const bridgeContract = new ethers_1.ethers.Contract(this.BRIDGE_SCRIPT_HASH, bridge_1.BRIDGE_ABI);
|
|
107
|
+
const to = '0x' + neon_js_1.wallet.getScriptHashFromAddress(params.receiverAddress);
|
|
108
|
+
const bridgeFee = ethers_1.ethers.utils.parseUnits(params.bridgeFee, BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET.decimals);
|
|
109
|
+
const isNativeToken = blockchain_service_1.BSTokenHelper.predicateByHash(params.token)(BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET);
|
|
110
|
+
let bridgeTransactionParam = {
|
|
111
|
+
type: 2,
|
|
112
|
+
};
|
|
113
|
+
if (isNativeToken) {
|
|
114
|
+
const populatedTransaction = yield bridgeContract.populateTransaction.withdrawNative(to, bridgeFee);
|
|
115
|
+
bridgeTransactionParam = Object.assign(Object.assign(Object.assign({}, bridgeTransactionParam), populatedTransaction), { value: ethers_1.ethers.utils.parseUnits(params.amount, params.token.decimals) });
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const approveTransactionParam = yield __classPrivateFieldGet(this, _Neo3NeoXBridgeService_instances, "m", _Neo3NeoXBridgeService_buildApproveTransactionParam).call(this, params);
|
|
119
|
+
if (approveTransactionParam) {
|
|
120
|
+
const approveTransaction = yield signer.sendTransaction(approveTransactionParam);
|
|
121
|
+
yield approveTransaction.wait();
|
|
122
|
+
}
|
|
123
|
+
const fixedAmount = blockchain_service_1.BSBigNumberHelper.format(params.amount, { decimals: 0 });
|
|
124
|
+
const amount = ethers_1.ethers.utils.parseUnits(fixedAmount, params.token.decimals);
|
|
125
|
+
const populatedTransaction = yield bridgeContract.populateTransaction.withdrawToken(params.token.hash, to, amount);
|
|
126
|
+
bridgeTransactionParam = Object.assign(Object.assign(Object.assign({}, bridgeTransactionParam), populatedTransaction), { value: bridgeFee });
|
|
109
127
|
}
|
|
110
128
|
let gasLimit;
|
|
111
129
|
try {
|
|
@@ -114,201 +132,80 @@ class Neo3NeoXBridgeService {
|
|
|
114
132
|
catch (_a) {
|
|
115
133
|
gasLimit = bs_ethereum_1.BSEthereumConstants.DEFAULT_GAS_LIMIT;
|
|
116
134
|
}
|
|
135
|
+
const gasPrice = yield signer.getGasPrice();
|
|
117
136
|
const transaction = yield signer.sendTransaction(Object.assign(Object.assign({}, bridgeTransactionParam), { gasLimit, maxPriorityFeePerGas: gasPrice, maxFeePerGas: gasPrice }));
|
|
118
137
|
return transaction.hash;
|
|
119
138
|
});
|
|
120
139
|
}
|
|
121
|
-
|
|
140
|
+
getNonce(params) {
|
|
122
141
|
return __awaiter(this, void 0, void 0, function* () {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (isGasToken) {
|
|
129
|
-
return __classPrivateFieldGet(this, _Neo3NeoXBridgeService_instances, "m", _Neo3NeoXBridgeService_validateGas).call(this, params);
|
|
142
|
+
let data;
|
|
143
|
+
try {
|
|
144
|
+
const client = BlockscoutBDSNeoX_1.BlockscoutBDSNeoX.getClient(__classPrivateFieldGet(this, _Neo3NeoXBridgeService_service, "f").network);
|
|
145
|
+
const response = yield client.get(`/transactions/${params.transactionHash}/logs`);
|
|
146
|
+
data = response.data;
|
|
130
147
|
}
|
|
131
|
-
|
|
132
|
-
|
|
148
|
+
catch (error) {
|
|
149
|
+
throw new blockchain_service_1.BSError('Transaction logs not found', 'LOGS_NOT_FOUND', error);
|
|
133
150
|
}
|
|
134
|
-
|
|
135
|
-
throw new blockchain_service_1.BSError('
|
|
151
|
+
if (!data.items || data.items.length === 0) {
|
|
152
|
+
throw new blockchain_service_1.BSError('Transaction logs not found', 'LOGS_NOT_FOUND');
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
const BridgeInterface = new ethers_1.ethers.utils.Interface(bridge_1.BRIDGE_ABI);
|
|
156
|
+
const isNativeToken = blockchain_service_1.BSTokenHelper.predicateByHash(params.token)(BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET);
|
|
157
|
+
if (isNativeToken) {
|
|
158
|
+
const item = data.items[0];
|
|
159
|
+
const parsedLog = BridgeInterface.parseLog({ data: item.data, topics: item.topics.filter(Boolean) });
|
|
160
|
+
return parsedLog.args.nonce ? parsedLog.args.nonce.toString() : null;
|
|
161
|
+
}
|
|
162
|
+
const item = data.items[1];
|
|
163
|
+
const parsedLog = BridgeInterface.parseLog({ data: item.data, topics: item.topics.filter(Boolean) });
|
|
164
|
+
return parsedLog.args.nonce ? parsedLog.args.nonce.toString() : null;
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
return null;
|
|
136
168
|
}
|
|
137
169
|
});
|
|
138
170
|
}
|
|
139
|
-
|
|
171
|
+
getTransactionHashByNonce(params) {
|
|
172
|
+
var _a, _b;
|
|
140
173
|
return __awaiter(this, void 0, void 0, function* () {
|
|
141
|
-
if (!BSNeoXHelper_1.BSNeoXHelper.isMainnet(__classPrivateFieldGet(this, _Neo3NeoXBridgeService_service, "f").network))
|
|
142
|
-
throw new blockchain_service_1.BSError('Bridging to Neo3 is only supported on mainnet', 'UNSUPPORTED_NETWORK');
|
|
143
174
|
try {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
const { data } = yield client.get(`/transactions/${transactionHash}/logs`);
|
|
149
|
-
if (!data.items || data.items.length === 0) {
|
|
150
|
-
throw new blockchain_service_1.BSError('Transaction logs not found', 'LOGS_NOT_FOUND');
|
|
151
|
-
}
|
|
152
|
-
return data;
|
|
153
|
-
}), {
|
|
154
|
-
retries: 10,
|
|
155
|
-
delay: 30000,
|
|
156
|
-
});
|
|
157
|
-
const BridgeInterface = new ethers_1.ethers.utils.Interface(bridge_1.BRIDGE_ABI);
|
|
158
|
-
const isGasToken = blockchain_service_1.BSTokenHelper.predicateByHash(validatedInputs.token)(BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET);
|
|
159
|
-
if (isGasToken) {
|
|
160
|
-
const item = log.items[0];
|
|
161
|
-
const response = BridgeInterface.decodeEventLog('NativeWithdrawal', item.data, item.topics.filter(Boolean));
|
|
162
|
-
nonce = response.nonce.toString();
|
|
175
|
+
let url;
|
|
176
|
+
const isNativeToken = blockchain_service_1.BSTokenHelper.predicateByHash(params.token)(BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET);
|
|
177
|
+
if (isNativeToken) {
|
|
178
|
+
url = `${this.BRIDGE_BASE_CONFIRMATION_URL}/${params.nonce}`;
|
|
163
179
|
}
|
|
164
180
|
else {
|
|
165
|
-
|
|
166
|
-
const response = BridgeInterface.decodeEventLog('TokenWithdrawal', item.data, item.topics.filter(Boolean));
|
|
167
|
-
nonce = response.nonce.toString();
|
|
181
|
+
url = `${this.BRIDGE_BASE_CONFIRMATION_URL}/${BSNeoXConstants_1.BSNeoXConstants.NEO_TOKEN.hash}/${params.nonce}`;
|
|
168
182
|
}
|
|
169
|
-
|
|
170
|
-
|
|
183
|
+
const response = yield axios_1.default.get(url);
|
|
184
|
+
if (!((_a = response.data) === null || _a === void 0 ? void 0 : _a.txid)) {
|
|
185
|
+
throw new blockchain_service_1.BSError('Transaction not found', 'TRANSACTION_NOT_FOUND');
|
|
171
186
|
}
|
|
172
|
-
|
|
173
|
-
var _a, _b;
|
|
174
|
-
const response = yield axios_1.default.post('https://neofura.ngd.network', {
|
|
175
|
-
jsonrpc: '2.0',
|
|
176
|
-
method: 'GetBridgeTxByNonce',
|
|
177
|
-
params: {
|
|
178
|
-
ContractHash: this.BRIDGE_SCRIPT_HASH,
|
|
179
|
-
TokenHash: isGasToken ? '' : this.BRIDGE_NEO3_NEO_TOKEN_HASH,
|
|
180
|
-
Nonce: Number(nonce),
|
|
181
|
-
},
|
|
182
|
-
id: 1,
|
|
183
|
-
});
|
|
184
|
-
if (!((_a = response.data) === null || _a === void 0 ? void 0 : _a.result.Vmstate) || !((_b = response.data) === null || _b === void 0 ? void 0 : _b.result.txid)) {
|
|
185
|
-
throw new blockchain_service_1.BSError('Transaction not found', 'TRANSACTION_NOT_FOUND');
|
|
186
|
-
}
|
|
187
|
-
if (response.data.result.Vmstate !== 'HALT') {
|
|
188
|
-
throw new blockchain_service_1.BSError('Transaction is not in a valid state', 'INVALID_TRANSACTION_STATE');
|
|
189
|
-
}
|
|
190
|
-
}), {
|
|
191
|
-
retries: 10,
|
|
192
|
-
delay: 30000,
|
|
193
|
-
});
|
|
194
|
-
return true;
|
|
187
|
+
return (_b = response.data) === null || _b === void 0 ? void 0 : _b.txid;
|
|
195
188
|
}
|
|
196
189
|
catch (error) {
|
|
197
|
-
|
|
190
|
+
throw new blockchain_service_1.BSError('Transaction not found', 'TRANSACTION_NOT_FOUND', error);
|
|
198
191
|
}
|
|
199
192
|
});
|
|
200
193
|
}
|
|
201
194
|
}
|
|
202
195
|
exports.Neo3NeoXBridgeService = Neo3NeoXBridgeService;
|
|
203
|
-
_Neo3NeoXBridgeService_service = new WeakMap(), _Neo3NeoXBridgeService_instances = new WeakSet(),
|
|
196
|
+
_Neo3NeoXBridgeService_service = new WeakMap(), _Neo3NeoXBridgeService_instances = new WeakSet(), _Neo3NeoXBridgeService_buildApproveTransactionParam = function _Neo3NeoXBridgeService_buildApproveTransactionParam(params) {
|
|
204
197
|
return __awaiter(this, void 0, void 0, function* () {
|
|
205
198
|
const provider = new ethers_1.ethers.providers.JsonRpcProvider(__classPrivateFieldGet(this, _Neo3NeoXBridgeService_service, "f").network.url);
|
|
206
|
-
const
|
|
207
|
-
const to = '0x' + neon_js_1.wallet.getScriptHashFromAddress(params.receiverAddress);
|
|
208
|
-
const bridgeContract = new ethers_1.ethers.Contract(this.BRIDGE_SCRIPT_HASH, bridge_1.BRIDGE_ABI);
|
|
209
|
-
const bridgeFee = ethers_1.ethers.utils.parseUnits(this.BRIDGE_GAS_FEE.toString(), BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET.decimals);
|
|
210
|
-
const populatedTransaction = yield bridgeContract.populateTransaction.withdrawNative(to, bridgeFee);
|
|
211
|
-
const bridgeTransactionParam = Object.assign(Object.assign({}, populatedTransaction), { value: ethers_1.ethers.utils.parseUnits(params.validatedInputs.amount, params.validatedInputs.token.decimals), type: 2 });
|
|
212
|
-
return {
|
|
213
|
-
bridgeTransactionParam,
|
|
214
|
-
approveTransactionParams: undefined,
|
|
215
|
-
gasPrice,
|
|
216
|
-
};
|
|
217
|
-
});
|
|
218
|
-
}, _Neo3NeoXBridgeService_buildNeoTransactionParams = function _Neo3NeoXBridgeService_buildNeoTransactionParams(params) {
|
|
219
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
220
|
-
const provider = new ethers_1.ethers.providers.JsonRpcProvider(__classPrivateFieldGet(this, _Neo3NeoXBridgeService_service, "f").network.url);
|
|
221
|
-
const gasPrice = yield provider.getGasPrice();
|
|
222
|
-
const to = '0x' + neon_js_1.wallet.getScriptHashFromAddress(params.receiverAddress);
|
|
223
|
-
const bridgeContract = new ethers_1.ethers.Contract(this.BRIDGE_SCRIPT_HASH, bridge_1.BRIDGE_ABI);
|
|
224
|
-
const bridgeFee = ethers_1.ethers.utils.parseUnits(this.BRIDGE_GAS_FEE.toString(), BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET.decimals);
|
|
225
|
-
// We are using 0 as the decimals because the NEO token in Neo3 has 0 decimals
|
|
226
|
-
const fixedAmount = blockchain_service_1.BSBigNumberHelper.format(params.validatedInputs.amount, { decimals: 0 });
|
|
227
|
-
const amount = ethers_1.ethers.utils.parseUnits(fixedAmount, params.validatedInputs.token.decimals);
|
|
228
|
-
const erc20Contract = new ethers_1.ethers.Contract(BSNeoXConstants_1.BSNeoXConstants.NEO_TOKEN.hash, bs_ethereum_1.ERC20_ABI, provider);
|
|
199
|
+
const erc20Contract = new ethers_1.ethers.Contract(params.token.hash, bs_ethereum_1.ERC20_ABI, provider);
|
|
229
200
|
const allowance = yield erc20Contract.allowance(params.account.address, this.BRIDGE_SCRIPT_HASH);
|
|
230
201
|
const allowanceNumber = blockchain_service_1.BSBigNumberHelper.fromDecimals(allowance.toString(), BSNeoXConstants_1.BSNeoXConstants.NEO_TOKEN.decimals);
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
const populatedTransaction = yield bridgeContract.populateTransaction.withdrawToken(params.validatedInputs.token.hash, to, amount);
|
|
237
|
-
const bridgeTransactionParam = Object.assign(Object.assign({}, populatedTransaction), { type: 2, value: bridgeFee });
|
|
238
|
-
return {
|
|
239
|
-
bridgeTransactionParam,
|
|
240
|
-
approveTransactionParams,
|
|
241
|
-
gasPrice,
|
|
242
|
-
};
|
|
243
|
-
});
|
|
244
|
-
}, _Neo3NeoXBridgeService_buildTransactionParams = function _Neo3NeoXBridgeService_buildTransactionParams(params) {
|
|
245
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
246
|
-
const isGasToken = blockchain_service_1.BSTokenHelper.predicateByHash(params.validatedInputs.token)(BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET);
|
|
247
|
-
if (isGasToken) {
|
|
248
|
-
return __classPrivateFieldGet(this, _Neo3NeoXBridgeService_instances, "m", _Neo3NeoXBridgeService_buildGasTransactionParams).call(this, params);
|
|
249
|
-
}
|
|
250
|
-
return __classPrivateFieldGet(this, _Neo3NeoXBridgeService_instances, "m", _Neo3NeoXBridgeService_buildNeoTransactionParams).call(this, params);
|
|
251
|
-
});
|
|
252
|
-
}, _Neo3NeoXBridgeService_validateGas = function _Neo3NeoXBridgeService_validateGas({ amount, balances, token, account, receiverAddress, }) {
|
|
253
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
254
|
-
const gasBalance = balances.find(balance => bs_ethereum_1.BSEthereumTokenHelper.predicateByHash(balance.token)(BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET));
|
|
255
|
-
if (!gasBalance) {
|
|
256
|
-
throw new blockchain_service_1.BSError('GAS is necessary to bridge', 'GAS_BALANCE_NOT_FOUND');
|
|
257
|
-
}
|
|
258
|
-
const amountNumber = blockchain_service_1.BSBigNumberHelper.fromNumber(amount);
|
|
259
|
-
const gasBalanceNumber = blockchain_service_1.BSBigNumberHelper.fromNumber(gasBalance.amount);
|
|
260
|
-
const validatedInputs = {
|
|
261
|
-
receiveAmount: amountNumber.minus(this.BRIDGE_GAS_FEE).toString(),
|
|
262
|
-
token,
|
|
263
|
-
amount,
|
|
264
|
-
};
|
|
265
|
-
if (amountNumber.isLessThan(this.BRIDGE_MIN_AMOUNT + this.BRIDGE_GAS_FEE)) {
|
|
266
|
-
throw new blockchain_service_1.BSError('Amount is less than the minimum amount plus bridge fee', 'AMOUNT_TOO_LOW');
|
|
267
|
-
}
|
|
268
|
-
if (amountNumber.isGreaterThan(gasBalanceNumber)) {
|
|
269
|
-
throw new blockchain_service_1.BSError('Amount is greater than your balance', 'INSUFFICIENT_GAS_BALANCE');
|
|
270
|
-
}
|
|
271
|
-
const fee = yield this.calculateFee({
|
|
272
|
-
account,
|
|
273
|
-
receiverAddress,
|
|
274
|
-
validatedInputs,
|
|
275
|
-
});
|
|
276
|
-
if (amountNumber.plus(fee).isGreaterThan(gasBalanceNumber)) {
|
|
277
|
-
throw new blockchain_service_1.BSError('Amount is greater than your balance plus fee', 'INSUFFICIENT_GAS_BALANCE_FEE');
|
|
278
|
-
}
|
|
279
|
-
return validatedInputs;
|
|
280
|
-
});
|
|
281
|
-
}, _Neo3NeoXBridgeService_validateNeo = function _Neo3NeoXBridgeService_validateNeo({ amount, balances, token, account, receiverAddress, }) {
|
|
282
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
283
|
-
const gasBalance = balances.find(balance => bs_ethereum_1.BSEthereumTokenHelper.predicateByHash(balance.token)(BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET));
|
|
284
|
-
if (!gasBalance) {
|
|
285
|
-
throw new blockchain_service_1.BSError('GAS is necessary to bridge', 'GAS_BALANCE_NOT_FOUND');
|
|
286
|
-
}
|
|
287
|
-
const neoBalance = balances.find(balance => bs_ethereum_1.BSEthereumTokenHelper.predicateByHash(balance.token)(BSNeoXConstants_1.BSNeoXConstants.NEO_TOKEN));
|
|
288
|
-
if (!neoBalance) {
|
|
289
|
-
throw new blockchain_service_1.BSError('NEO balance not found', 'NEO_BALANCE_NOT_FOUND');
|
|
290
|
-
}
|
|
291
|
-
const amountNumber = blockchain_service_1.BSBigNumberHelper.fromNumber(amount);
|
|
292
|
-
const gasBalanceNumber = blockchain_service_1.BSBigNumberHelper.fromNumber(gasBalance.amount);
|
|
293
|
-
const minGasBalanceNumber = blockchain_service_1.BSBigNumberHelper.fromNumber(this.BRIDGE_GAS_FEE);
|
|
294
|
-
const validatedInputs = { receiveAmount: amount, token, amount };
|
|
295
|
-
if (amountNumber.isLessThan(this.BRIDGE_MIN_AMOUNT)) {
|
|
296
|
-
throw new blockchain_service_1.BSError('Amount is less than the minimum amount', 'AMOUNT_TOO_LOW');
|
|
297
|
-
}
|
|
298
|
-
if (amountNumber.isGreaterThan(neoBalance.amount)) {
|
|
299
|
-
throw new blockchain_service_1.BSError('Amount is greater than your balance', 'INSUFFICIENT_NEO_BALANCE');
|
|
300
|
-
}
|
|
301
|
-
if (gasBalanceNumber.isLessThan(minGasBalanceNumber)) {
|
|
302
|
-
throw new blockchain_service_1.BSError('GAS balance is less than bridge fee', 'INSUFFICIENT_GAS_BALANCE_BRIDGE_FEE');
|
|
303
|
-
}
|
|
304
|
-
const fee = yield this.calculateFee({
|
|
305
|
-
account,
|
|
306
|
-
receiverAddress,
|
|
307
|
-
validatedInputs,
|
|
308
|
-
});
|
|
309
|
-
if (minGasBalanceNumber.plus(fee).isGreaterThan(gasBalanceNumber)) {
|
|
310
|
-
throw new blockchain_service_1.BSError('GAS balance is less than fees', 'INSUFFICIENT_GAS_BALANCE_FEES');
|
|
202
|
+
// We are using 0 as the decimals because the NEO token in Neo3 has 0 decimals
|
|
203
|
+
const fixedAmount = blockchain_service_1.BSBigNumberHelper.format(params.amount, { decimals: 0 });
|
|
204
|
+
if (allowanceNumber.isGreaterThanOrEqualTo(fixedAmount)) {
|
|
205
|
+
return null;
|
|
311
206
|
}
|
|
312
|
-
|
|
207
|
+
const amount = ethers_1.ethers.utils.parseUnits(fixedAmount, params.token.decimals);
|
|
208
|
+
const populatedApproveTransaction = yield erc20Contract.populateTransaction.approve(this.BRIDGE_SCRIPT_HASH, amount);
|
|
209
|
+
return populatedApproveTransaction;
|
|
313
210
|
});
|
|
314
211
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cityofzion/bs-neox",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"repository": "https://github.com/CityOfZion/blockchain-services",
|
|
@@ -11,19 +11,20 @@
|
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@cityofzion/dora-ts": "0.5.1",
|
|
14
|
-
"@cityofzion/neon-js": "5.7.0",
|
|
15
|
-
"@ledgerhq/hw-transport": "~6.
|
|
14
|
+
"@cityofzion/neon-js": "~5.7.0",
|
|
15
|
+
"@ledgerhq/hw-transport": "~6.31.8",
|
|
16
16
|
"axios": "1.8.2",
|
|
17
17
|
"ethers": "5.7.2",
|
|
18
18
|
"date-fns": "~4.1.0",
|
|
19
|
-
"@cityofzion/blockchain-service": "1.19.
|
|
20
|
-
"@cityofzion/bs-ethereum": "2.12.
|
|
19
|
+
"@cityofzion/blockchain-service": "1.19.2",
|
|
20
|
+
"@cityofzion/bs-ethereum": "2.12.7"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@ledgerhq/hw-transport-node-hid": "~6.
|
|
23
|
+
"@ledgerhq/hw-transport-node-hid": "~6.29.9",
|
|
24
24
|
"@types/jest": "29.5.3",
|
|
25
25
|
"@typescript-eslint/eslint-plugin": "^6.5.0",
|
|
26
26
|
"@typescript-eslint/parser": "^6.5.0",
|
|
27
|
+
"bignumber.js": "~9.3.0",
|
|
27
28
|
"dotenv": "16.3.1",
|
|
28
29
|
"eslint": "^8.48.0",
|
|
29
30
|
"jest": "29.6.2",
|