@cityofzion/bs-neox 1.2.3 → 1.2.5
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<BSName>[];
|
|
10
8
|
constructor(service: BSNeoX<BSName>);
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
getBridgeConstants(token: TBridgeToken<BSName>): Promise<TNeo3NeoXBridgeServiceConstants>;
|
|
10
|
+
getApprovalFee(params: TNeo3NeoXBridgeServiceGetApprovalParam<BSName>): Promise<string>;
|
|
13
11
|
bridge(params: TNeo3NeoXBridgeServiceBridgeParam<BSName>): Promise<string>;
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
getNonce(params: TNeo3NeoXBridgeServiceGetNonceParams<BSName>): Promise<string>;
|
|
13
|
+
getTransactionHashByNonce(params: TNeo3NeoXBridgeServiceGetTransactionHashByNonceParams<BSName>): Promise<string>;
|
|
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', blockchain: service.name }),
|
|
46
|
+
Object.assign(Object.assign({}, BSNeoXConstants_1.BSNeoXConstants.NEO_TOKEN), { multichainId: 'neo', blockchain: service.name }),
|
|
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,213 +103,116 @@ 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).add(bridgeFee) });
|
|
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 {
|
|
112
130
|
gasLimit = yield signer.estimateGas(bridgeTransactionParam);
|
|
113
131
|
}
|
|
114
|
-
catch (
|
|
132
|
+
catch (error) {
|
|
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
|
-
|
|
129
|
-
|
|
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;
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
throw new blockchain_service_1.BSError('Failed to get nonce from transaction log', 'FAILED_TO_GET_NONCE', error);
|
|
130
150
|
}
|
|
131
|
-
|
|
132
|
-
|
|
151
|
+
if (!data.items || data.items.length === 0) {
|
|
152
|
+
throw new blockchain_service_1.BSError('Transaction invalid', 'INVALID_TRANSACTION');
|
|
133
153
|
}
|
|
134
|
-
|
|
135
|
-
|
|
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
|
+
let nonce;
|
|
158
|
+
if (isNativeToken) {
|
|
159
|
+
const item = data.items[0];
|
|
160
|
+
const parsedLog = BridgeInterface.parseLog({ data: item.data, topics: item.topics.filter(Boolean) });
|
|
161
|
+
nonce = parsedLog.args.nonce ? parsedLog.args.nonce.toString() : undefined;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
const item = data.items[1];
|
|
165
|
+
const parsedLog = BridgeInterface.parseLog({ data: item.data, topics: item.topics.filter(Boolean) });
|
|
166
|
+
nonce = parsedLog.args.nonce ? parsedLog.args.nonce.toString() : undefined;
|
|
167
|
+
}
|
|
168
|
+
if (!nonce) {
|
|
169
|
+
throw new blockchain_service_1.BSError('Nonce not found in transaction log', 'NONCE_NOT_FOUND');
|
|
170
|
+
}
|
|
171
|
+
return nonce;
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
throw new blockchain_service_1.BSError('Failed to get nonce from transaction log', 'FAILED_TO_GET_NONCE', error);
|
|
136
175
|
}
|
|
137
176
|
});
|
|
138
177
|
}
|
|
139
|
-
|
|
178
|
+
getTransactionHashByNonce(params) {
|
|
179
|
+
var _a;
|
|
140
180
|
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
181
|
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();
|
|
182
|
+
let url;
|
|
183
|
+
const isNativeToken = blockchain_service_1.BSTokenHelper.predicateByHash(params.token)(BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET);
|
|
184
|
+
if (isNativeToken) {
|
|
185
|
+
url = `${this.BRIDGE_BASE_CONFIRMATION_URL}/${params.nonce}`;
|
|
163
186
|
}
|
|
164
187
|
else {
|
|
165
|
-
|
|
166
|
-
const response = BridgeInterface.decodeEventLog('TokenWithdrawal', item.data, item.topics.filter(Boolean));
|
|
167
|
-
nonce = response.nonce.toString();
|
|
188
|
+
url = `${this.BRIDGE_BASE_CONFIRMATION_URL}/${BSNeoXConstants_1.BSNeoXConstants.NEO_TOKEN.hash}/${params.nonce}`;
|
|
168
189
|
}
|
|
169
|
-
|
|
170
|
-
|
|
190
|
+
const response = yield axios_1.default.get(url);
|
|
191
|
+
if (!((_a = response.data) === null || _a === void 0 ? void 0 : _a.txid)) {
|
|
192
|
+
throw new blockchain_service_1.BSError('Transaction ID not found in response', 'TXID_NOT_FOUND');
|
|
171
193
|
}
|
|
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;
|
|
194
|
+
return response.data.txid;
|
|
195
195
|
}
|
|
196
196
|
catch (error) {
|
|
197
|
-
|
|
197
|
+
throw new blockchain_service_1.BSError('Transaction ID not found in response', 'TXID_NOT_FOUND', error);
|
|
198
198
|
}
|
|
199
199
|
});
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
exports.Neo3NeoXBridgeService = Neo3NeoXBridgeService;
|
|
203
|
-
_Neo3NeoXBridgeService_service = new WeakMap(), _Neo3NeoXBridgeService_instances = new WeakSet(),
|
|
203
|
+
_Neo3NeoXBridgeService_service = new WeakMap(), _Neo3NeoXBridgeService_instances = new WeakSet(), _Neo3NeoXBridgeService_buildApproveTransactionParam = function _Neo3NeoXBridgeService_buildApproveTransactionParam(params) {
|
|
204
204
|
return __awaiter(this, void 0, void 0, function* () {
|
|
205
205
|
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);
|
|
206
|
+
const erc20Contract = new ethers_1.ethers.Contract(params.token.hash, bs_ethereum_1.ERC20_ABI, provider);
|
|
229
207
|
const allowance = yield erc20Contract.allowance(params.account.address, this.BRIDGE_SCRIPT_HASH);
|
|
230
208
|
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');
|
|
209
|
+
// We are using 0 as the decimals because the NEO token in Neo3 has 0 decimals
|
|
210
|
+
const fixedAmount = blockchain_service_1.BSBigNumberHelper.format(params.amount, { decimals: 0 });
|
|
211
|
+
if (allowanceNumber.isGreaterThanOrEqualTo(fixedAmount)) {
|
|
212
|
+
return null;
|
|
311
213
|
}
|
|
312
|
-
|
|
214
|
+
const amount = ethers_1.ethers.utils.parseUnits(fixedAmount, params.token.decimals);
|
|
215
|
+
const populatedApproveTransaction = yield erc20Contract.populateTransaction.approve(this.BRIDGE_SCRIPT_HASH, amount);
|
|
216
|
+
return populatedApproveTransaction;
|
|
313
217
|
});
|
|
314
218
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cityofzion/bs-neox",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
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.3",
|
|
20
|
+
"@cityofzion/bs-ethereum": "2.12.8"
|
|
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",
|