@cityofzion/bs-neox 1.2.2 → 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, TNeo3NeoXBridgeServiceCalculateMaxAmountParams, TNeo3NeoXBridgeServiceValidatedInputs, TNeo3NeoXBridgeServiceValidateInputParams, TNeo3NeoXBridgeServiceWaitParams } from '@cityofzion/blockchain-service';
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 BRIDGE_GAS_FEE = 0.1;
7
- readonly BRIDGE_MIN_AMOUNT = 1;
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
- calculateMaxAmount({ account, balances, receiverAddress, token, }: TNeo3NeoXBridgeServiceCalculateMaxAmountParams<BSName>): Promise<string>;
12
- calculateFee(params: TNeo3NeoXBridgeServiceBridgeParam<BSName>): Promise<string>;
9
+ getBridgeConstants(token: TBridgeToken): Promise<TNeo3NeoXBridgeServiceConstants>;
10
+ getApprovalFee(params: TNeo3NeoXBridgeServiceGetApprovalParam<BSName>): Promise<string>;
13
11
  bridge(params: TNeo3NeoXBridgeServiceBridgeParam<BSName>): Promise<string>;
14
- validateInputs(params: TNeo3NeoXBridgeServiceValidateInputParams<BSName>): Promise<TNeo3NeoXBridgeServiceValidatedInputs>;
15
- wait(params: TNeo3NeoXBridgeServiceWaitParams): Promise<boolean>;
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, _Neo3NeoXBridgeService_buildGasTransactionParams, _Neo3NeoXBridgeService_buildNeoTransactionParams, _Neo3NeoXBridgeService_buildTransactionParams, _Neo3NeoXBridgeService_validateGas, _Neo3NeoXBridgeService_validateNeo;
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.BRIDGE_GAS_FEE = 0.1;
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
- calculateMaxAmount({ account, balances, receiverAddress, token, }) {
49
+ getBridgeConstants(token) {
49
50
  return __awaiter(this, void 0, void 0, function* () {
50
- if (!BSNeoXHelper_1.BSNeoXHelper.isMainnet(__classPrivateFieldGet(this, _Neo3NeoXBridgeService_service, "f").network))
51
- throw new blockchain_service_1.BSError('Bridging to Neo3 is only supported on mainnet', 'UNSUPPORTED_NETWORK');
52
- const normalizedSelectedToken = bs_ethereum_1.BSEthereumTokenHelper.normalizeToken(token);
53
- const selectedTokenBalance = balances.find(balance => bs_ethereum_1.BSEthereumTokenHelper.normalizeHash(balance.token.hash) === normalizedSelectedToken.hash);
54
- if (!selectedTokenBalance) {
55
- throw new blockchain_service_1.BSError('Token balance not found', 'TOKEN_BALANCE_NOT_FOUND');
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
- calculateFee(params) {
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 signer = yield __classPrivateFieldGet(this, _Neo3NeoXBridgeService_service, "f").generateSigner(params.account);
75
- const { gasPrice, approveTransactionParams, bridgeTransactionParam } = yield __classPrivateFieldGet(this, _Neo3NeoXBridgeService_instances, "m", _Neo3NeoXBridgeService_buildTransactionParams).call(this, params);
76
- let fee = ethers_1.ethers.utils.parseEther('0');
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
- else {
83
- let approvedEstimated = ethers_1.ethers.utils.parseEther('0');
84
- if (approveTransactionParams) {
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
- return ethers_1.ethers.utils.formatEther(fee);
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
- throw new blockchain_service_1.BSError(error.message, 'FEE_CALCULATION_ERROR');
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 { approveTransactionParams, bridgeTransactionParam, gasPrice } = yield __classPrivateFieldGet(this, _Neo3NeoXBridgeService_instances, "m", _Neo3NeoXBridgeService_buildTransactionParams).call(this, params);
106
- if (approveTransactionParams) {
107
- const approveTransaction = yield signer.sendTransaction(approveTransactionParams);
108
- yield approveTransaction.wait();
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
- validateInputs(params) {
140
+ getNonce(params) {
122
141
  return __awaiter(this, void 0, void 0, function* () {
123
- if (!BSNeoXHelper_1.BSNeoXHelper.isMainnet(__classPrivateFieldGet(this, _Neo3NeoXBridgeService_service, "f").network))
124
- throw new blockchain_service_1.BSError('Bridging to Neo3 is only supported on mainnet', 'UNSUPPORTED_NETWORK');
125
- const normalizedSelectedToken = bs_ethereum_1.BSEthereumTokenHelper.normalizeToken(params.token);
126
- const isGasToken = normalizedSelectedToken.hash === BSNeoXConstants_1.BSNeoXConstants.NATIVE_ASSET.hash;
127
- const isNeoToken = normalizedSelectedToken.hash === BSNeoXConstants_1.BSNeoXConstants.NEO_TOKEN.hash;
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
- else if (isNeoToken) {
132
- return __classPrivateFieldGet(this, _Neo3NeoXBridgeService_instances, "m", _Neo3NeoXBridgeService_validateNeo).call(this, params);
148
+ catch (error) {
149
+ throw new blockchain_service_1.BSError('Transaction logs not found', 'LOGS_NOT_FOUND', error);
133
150
  }
134
- else {
135
- throw new blockchain_service_1.BSError('Only GAS and NEO tokens are supported for bridging', 'UNSUPPORTED_TOKEN');
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
- wait(params) {
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
- const { transactionHash, validatedInputs } = params;
145
- let nonce;
146
- const log = yield blockchain_service_1.BSUtilsHelper.retry(() => __awaiter(this, void 0, void 0, function* () {
147
- const client = BlockscoutBDSNeoX_1.BlockscoutBDSNeoX.getClient(__classPrivateFieldGet(this, _Neo3NeoXBridgeService_service, "f").network);
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
- const item = log.items[1];
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
- if (!nonce) {
170
- throw new Error();
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
- yield blockchain_service_1.BSUtilsHelper.retry(() => __awaiter(this, void 0, void 0, function* () {
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
- return false;
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(), _Neo3NeoXBridgeService_buildGasTransactionParams = function _Neo3NeoXBridgeService_buildGasTransactionParams(params) {
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 gasPrice = yield provider.getGasPrice();
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
- let approveTransactionParams;
232
- if (allowanceNumber.isLessThan(fixedAmount)) {
233
- const populatedApproveTransaction = yield erc20Contract.populateTransaction.approve(this.BRIDGE_SCRIPT_HASH, amount);
234
- approveTransactionParams = Object.assign(Object.assign({}, populatedApproveTransaction), { type: 2 });
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
- return validatedInputs;
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.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.30.5",
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/bs-ethereum": "2.12.5",
20
- "@cityofzion/blockchain-service": "1.19.1"
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.28.5",
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",