Skip to content

Commit 3956565

Browse files
authored
Merge pull request #37 from kilnfi/transaction-status
feat: add transactions statuses per protocol
2 parents e3d4a79 + 3e07e38 commit 3956565

File tree

18 files changed

+240
-73
lines changed

18 files changed

+240
-73
lines changed

examples/ada.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { Kiln } from "../src/kiln";
2+
23
const fs = require('fs');
34

4-
const apiSecretPath = fs.readFileSync(__dirname + '/fireblocks_secret.key', 'utf8');
5+
const apiSecret = fs.readFileSync(__dirname + '/fireblocks_secret.key', 'utf8');
56

67
const f = async () => {
78
try {
@@ -13,9 +14,9 @@ const f = async () => {
1314
name: 'vault1',
1415
provider: 'fireblocks',
1516
fireblocksApiKey: '53aee35e-04b7-9314-8f28-135a66c8af2c',
16-
fireblocksSecretKeyPath: apiSecretPath,
17-
vaultAccountId: '7'
18-
}
17+
fireblocksSecretKey: apiSecret,
18+
vaultAccountId: '7',
19+
},
1920
],
2021
});
2122

@@ -27,13 +28,14 @@ const f = async () => {
2728
// 'addr_test1qpy358g8glafrucevf0rjpmzx2k5esn5uvjh7dzuakpdhv4g2egyt3y3qw6jrguz0lmyhxygjdg2ytaf5z6ueaety7dsmpcee5',
2829
// );
2930

30-
const tx = await k.ada.craftUnstakeTx(
31-
'addr_test1qpy358g8glafrucevf0rjpmzx2k5esn5uvjh7dzuakpdhv4g2egyt3y3qw6jrguz0lmyhxygjdg2ytaf5z6ueaety7dsmpcee5',
32-
);
33-
const txSigned = await k.ada.sign('vault1', tx);
34-
const hash = await k.ada.broadcast(txSigned);
35-
console.log(hash);
36-
} catch (err){
31+
// const tx = await k.ada.craftUnstakeTx(
32+
// 'addr_test1qpy358g8glafrucevf0rjpmzx2k5esn5uvjh7dzuakpdhv4g2egyt3y3qw6jrguz0lmyhxygjdg2ytaf5z6ueaety7dsmpcee5',
33+
// );
34+
// const txSigned = await k.ada.sign('vault1', tx);
35+
// const hash = await k.ada.broadcast(txSigned);
36+
const status = await k.ada.getTxStatus('aad008eec08f606f763837144d18275203406bdada7fc2a429c656c15952dd9c');
37+
console.log(status);
38+
} catch (err) {
3739
console.log(err);
3840
}
3941
};

examples/atom.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,22 @@ const f = async () => {
1919
});
2020

2121
try {
22-
const tx = await k.atom.craftStakeTx(
23-
'376acfff-e35d-4b7c-90da-c6acb8ea7197',
24-
'cosmos19c9fdh488vqjclltwp68jm50ydwyh36jqeatev',
25-
0.1,
26-
);
22+
// const tx = await k.atom.craftStakeTx(
23+
// '376acfff-e35d-4b7c-90da-c6acb8ea7197',
24+
// 'cosmos19c9fdh488vqjclltwp68jm50ydwyh36jqeatev',
25+
// 0.1,
26+
// );
2727
// const tx = await k.atom.craftUnstakeTx(
2828
// 'cosmos19c9fdh488vqjclltwp68jm50ydwyh36jqeatev',
2929
// 'cosmosvaloper17hskshytlrepzhas628uk00jvvppg7yfj3wpqz',
3030
// 0.1
3131
// );
3232

33-
const signedTx = await k.atom.sign('vault1', tx);
34-
const hash = await k.atom.broadcast(signedTx);
35-
console.log(hash);
33+
// const signedTx = await k.atom.sign('vault1', tx);
34+
// const hash = await k.atom.broadcast(signedTx);
35+
// console.log(hash);
36+
const tx = await k.atom.getTxStatus('B0493A93397438DAD6D5641CBDE8CF43CC7424E6A322A2F5CD3C3B7DF02161E5');
37+
console.log(tx);
3638
} catch (err){
3739
console.log(err);
3840
}

examples/eth.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ const apiSecret = fs.readFileSync(__dirname + '/fireblocks_secret.key', 'utf8');
77
const f = async () => {
88
const k = new Kiln({
99
testnet: true,
10-
// apiToken: 'kiln_dTkxUTFRdHBMZm9vNFFycFhDSTZCdlJsbjJZang5VnY6ejJoV3FCSTlyZlBtM2ZIM0RFRVVaM3NwTkZReHJXTDZWZUxJMWtWWlVrb3VNYUVzcE9Lakt4ZVplOG9vd1oyVw',
11-
apiToken: 'kiln_V1JKOW55SkZMOFZvMzBJYmw0aGQ3bkM3UFpIM2IzeXA6YkN6VG9BZW56OWQtUVlGRjNqRW10c1E3R0w2YkRKdjAxQW1Cem5ONnF4Sm1WLUx6STNoRWE2XzdXSVZIc2s0Ug',
10+
apiToken: 'kiln_dTkxUTFRdHBMZm9vNFFycFhDSTZCdlJsbjJZang5VnY6ZjF1SUw4d3R1ZDRxYUdreEwtV2sxcjdmbVFJYlhuMWFGUVduRjBkVFJscFdCaUc5bkV2WmpyTU9xb19pSjlsWg',
1211
integrations: [
1312
{
1413
name: 'vault1',
@@ -26,13 +25,16 @@ const f = async () => {
2625
'0x9cE658155A6f05FE4aef83b7Fa8F431D5e8CcB55',
2726
32,
2827
);
29-
console.log(tx);
3028
const txSigned = await k.eth.sign('vault1', tx);
31-
const receipt = await k.eth.broadcast(txSigned);
32-
console.log(receipt);
33-
34-
const rewards = await k.eth.getStakesRewards(['0xb15c8670d36abe47f03acaa3ba901ac433973048d43df4d2086de4c422ea4d3d0a6b63702d253c15712d3c85997f0071', 'a262bbe9197b0fe7ced73f8af4b13813e0e03a42d62bd223e96b31c8ba379d6c56835c6729647139963f3fade95f52f6']);
35-
console.log(rewards);
29+
const hash = await k.eth.broadcast(txSigned);
30+
//
31+
// const rewards = await k.eth.getStakesRewards(['0xb15c8670d36abe47f03acaa3ba901ac433973048d43df4d2086de4c422ea4d3d0a6b63702d253c15712d3c85997f0071', 'a262bbe9197b0fe7ced73f8af4b13813e0e03a42d62bd223e96b31c8ba379d6c56835c6729647139963f3fade95f52f6']);
32+
// console.log(rewards);
33+
if(hash){
34+
console.log(hash);
35+
const status = await k.eth.getTxStatus(hash);
36+
console.log(status);
37+
}
3638
} catch (err) {
3739
console.log(err);
3840
}

examples/near.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,17 @@ const f = async () => {
2626
// 10
2727
// );
2828

29-
const tx = await k.near.craftUnstakeTx(
30-
'373c6f8e84c6822a9f87035f65cccf899eef3fcdee61077041a93e1805bab24e',
31-
'kiln.pool.f863973.m0',
32-
5,
33-
);
34-
35-
const signedTx = await k.near.sign('vault1', tx);
36-
const hash = await k.near.broadcast(signedTx);
37-
console.log(hash);
29+
// const tx = await k.near.craftUnstakeTx(
30+
// '373c6f8e84c6822a9f87035f65cccf899eef3fcdee61077041a93e1805bab24e',
31+
// 'kiln.pool.f863973.m0',
32+
// 5,
33+
// );
34+
//
35+
// const signedTx = await k.near.sign('vault1', tx);
36+
// const hash = await k.near.broadcast(signedTx);
37+
// console.log(hash);
38+
const tx = await k.near.getTxStatus('7iRYHAtrerLh7VaL3N4CTPN7LDJvqXYk6Y1oNXzWk2VY');
39+
console.log(tx);
3840
} catch (err) {
3941
console.log(err);
4042
}

examples/sol.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ const f = async () => {
3939
// const hash = await k.sol.broadcast(signedTx);
4040
// console.log(hash);
4141

42-
const accounts = await k.sol.getAccountsRewards(['771254de-ac5a-4911-afdf-1d5b7e802dc9']);
43-
console.log(accounts);
42+
// const accounts = await k.sol.getAccountsRewards(['771254de-ac5a-4911-afdf-1d5b7e802dc9']);
43+
// console.log(accounts);
44+
const tx = await k.sol.getTxStatus('26GZcovnvTGvf5fXFysbtJkNob5r4K9v4H8ZU9tSm8oF5hgUuUm231cabS8LCiC1cqQMFiRkNRNEgqtiVwpr2Bek');
45+
console.log(tx);
4446
} catch (err){
4547
console.log(err);
4648
}

src/errors/integrations.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,11 @@ export class BroadcastError extends Error {
1717
super(message);
1818
this.name = 'BroadcastError';
1919
}
20+
}
21+
22+
export class GetTxStatusError extends Error {
23+
constructor(message: string) {
24+
super(message);
25+
this.name = 'GetTxStatusError';
26+
}
2027
}

src/kiln.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,6 @@ export class Kiln {
3636
this.sol = new SolService({ testnet, integrations, rpc: rpcs?.solana, });
3737
this.atom = new AtomService({ testnet, integrations, rpc: rpcs?.atom, });
3838
this.ada = new AdaService({ testnet, integrations });
39-
this.near = new NearService({ testnet, integrations });
39+
this.near = new NearService({ testnet, integrations, rpc: rpcs?.near });
4040
}
4141
}

src/services/ada.ts

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,30 @@ import {
2828
Withdrawals,
2929
} from '@emurgo/cardano-serialization-lib-nodejs';
3030
import { Service } from "./service";
31-
import { AdaStakeOptions, InternalAdaConfig, UTXO } from "../types/ada";
31+
import {
32+
AdaStakeOptions,
33+
AdaTxStatus,
34+
InternalAdaConfig,
35+
UTXO,
36+
} from "../types/ada";
3237
import {
3338
BlockFrostAPI,
3439
BlockfrostServerError,
3540
} from "@blockfrost/blockfrost-js";
36-
import { InvalidIntegration, InvalidSignature } from "../errors/integrations";
41+
import {
42+
BroadcastError,
43+
GetTxStatusError,
44+
InvalidIntegration,
45+
InvalidSignature,
46+
} from "../errors/integrations";
3747
import { ADDRESSES } from "../globals";
3848
import {
3949
CouldNotFetchSlot,
4050
CouldNotFetchStakeAddress,
41-
CouldNotHashStakeKey, NoRewardAddressFound,
42-
NoStakeAddressFound, NotEnoughFunds,
51+
CouldNotHashStakeKey,
52+
NoRewardAddressFound,
53+
NoStakeAddressFound,
54+
NotEnoughFunds,
4355
} from "../errors/ada";
4456

4557
const CARDANO_PARAMS = {
@@ -460,14 +472,34 @@ export class AdaService extends Service {
460472
async broadcast(transaction: Transaction): Promise<string | undefined> {
461473
try {
462474
return await this.client.txSubmit(transaction.to_bytes());
463-
} catch (error) {
475+
} catch (error: any) {
464476
// submit could fail if the transactions is rejected by cardano node
465477
if (error instanceof BlockfrostServerError && error.status_code === 400) {
466478
console.log(error.stack, error.error);
467479
} else {
468-
// rethrow other errors
469-
throw error;
480+
throw new BroadcastError(error);
470481
}
471482
}
472483
}
484+
485+
/**
486+
* Get transaction status
487+
* @param transactionHash
488+
*/
489+
async getTxStatus(transactionHash: string): Promise<AdaTxStatus> {
490+
try {
491+
const receipt = await this.client.txs(transactionHash);
492+
const block = await this.client.blocks(receipt.block);
493+
494+
// Confirmed transactions after 15 confirmations
495+
const status = block.confirmations > 15 ? 'success' : 'pending_confirmation';
496+
497+
return {
498+
status: status,
499+
txReceipt: receipt,
500+
};
501+
} catch (error: any) {
502+
throw new GetTxStatusError(error);
503+
}
504+
}
473505
}

src/services/atom.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
1-
import { BroadcastError, InvalidIntegration } from "../errors/integrations";
1+
import {
2+
BroadcastError,
3+
GetTxStatusError,
4+
InvalidIntegration,
5+
} from "../errors/integrations";
26
import { Service } from "./service";
37
import {
4-
coin,
8+
coin, IndexedTx,
59
MsgDelegateEncodeObject,
610
MsgUndelegateEncodeObject,
711
SigningStargateClient,
812
StargateClient,
913
StdFee,
1014
} from "@cosmjs/stargate";
11-
import { AtomStakeOptions, AtomTx, InternalAtomConfig } from "../types/atom";
15+
import {
16+
AtomStakeOptions,
17+
AtomTx,
18+
AtomTxStatus,
19+
InternalAtomConfig,
20+
} from "../types/atom";
1221
import { CouldNotFetchDelegation, InvalidStakeAmount } from "../errors/atom";
1322
import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx";
1423
import { Coin, OfflineSigner } from "@cosmjs/proto-signing";
@@ -168,6 +177,23 @@ export class AtomService extends Service {
168177
}
169178
}
170179

180+
/**
181+
* Get transaction status
182+
* @param transactionHash: hash of transaction
183+
*/
184+
async getTxStatus(transactionHash: string): Promise<AtomTxStatus | null> {
185+
try {
186+
const client = await this.getClient();
187+
const tx = await client.getTx(transactionHash);
188+
return tx ? {
189+
status: tx.code === 0 ? 'success' : 'error',
190+
txReceipt: tx
191+
} : null;
192+
} catch (e: any) {
193+
throw new GetTxStatusError(e);
194+
}
195+
}
196+
171197
/**
172198
* Get correct signer given integration. (only support fireblocks provider for now)
173199
* @param integration

src/services/eth.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ import {
88
EthereumStakeOptions,
99
EthereumTx,
1010
EthNetworkStats,
11-
EthStakes,
11+
EthStakes, EthTxStatus,
1212
InternalEthereumConfig,
1313
ValidationKeyDepositData,
1414
} from '../types/eth';
1515
import {
16-
BroadcastError,
16+
BroadcastError, GetTxStatusError,
1717
InvalidIntegration,
1818
InvalidSignature,
1919
} from "../errors/integrations";
@@ -95,19 +95,16 @@ export class EthService extends Service {
9595
);
9696

9797
const data = batchDepositFunction.encodeABI();
98-
const gasPrice = await batchDepositFunction.estimateGas({
99-
from: walletAddress,
100-
value: this.web3.utils.toWei(amountEth.toString(), 'ether'),
101-
});
98+
const gasWei = 100000 + nbKeysNeeded * 80000;
10299
const common = new Common({ chain: this.testnet ? Chain.Goerli : Chain.Mainnet });
103100
const nonce = await this.web3.eth.getTransactionCount(walletAddress);
104101
return Transaction.fromTxData({
105102
nonce: nonce,
106103
data: data,
107-
to: this.testnet ? ADDRESSES.eth.testnet.depositContract : ADDRESSES.eth.mainnet.depositContract,
108-
value: this.web3.utils.numberToHex(this.web3.utils.toWei(amountEth.toString(), 'ether')),
109-
gasPrice: this.web3.utils.numberToHex(gasPrice),
110-
gasLimit: this.web3.utils.numberToHex(100000),
104+
to: walletAddress,
105+
value: this.web3.utils.numberToHex(0),
106+
gasPrice: this.web3.utils.numberToHex(gasWei),
107+
gasLimit: this.web3.utils.numberToHex(gasWei),
111108
}, { common });
112109
} catch (err: any) {
113110
throw new Error(err);
@@ -174,6 +171,23 @@ export class EthService extends Service {
174171
}
175172
}
176173

174+
/**
175+
* Get transaction status
176+
* @param transactionHash: transaction hash
177+
*/
178+
async getTxStatus(transactionHash: string): Promise<EthTxStatus> {
179+
try {
180+
const receipt = await this.web3.eth.getTransactionReceipt(transactionHash);
181+
const status = receipt ? receipt.status ? 'success' : 'error' : 'pending_confirmation';
182+
return {
183+
status: status,
184+
txReceipt: receipt,
185+
};
186+
} catch (e: any) {
187+
throw new GetTxStatusError(e);
188+
}
189+
}
190+
177191
/**
178192
* Retrieve stakes of given kiln accounts
179193
* @param accountIds: account ids of which you wish to retrieve rewards

0 commit comments

Comments
 (0)