forked from fireblocks/fireblocks-defi-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
web3-bridge.ts
102 lines (91 loc) · 3.43 KB
/
web3-bridge.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import {
PeerType,
TransactionOperation,
CreateTransactionResponse,
TransactionStatus,
TransactionResponse,
TransactionArguments
} from "fireblocks-sdk";
import { BaseBridge } from "./base-bridge";
import * as BN from "bn.js";
import { formatEther, formatUnits } from "ethers/lib/utils";
import { TypedDataUtils } from "eth-sig-util";
export interface TransactionConfig {
from?: string | number;
to?: string;
value?: number | string | BN;
gas?: number | string;
gasPrice?: number | string | BN;
data?: string;
nonce?: number;
chainId?: number;
chain?: string;
hardfork?: string;
}
export class Web3Bridge extends BaseBridge {
async signTypedData(typedData, txNote) {
const content = TypedDataUtils.sign(typedData).toString("hex");
const transactionParams = {
operation: TransactionOperation.RAW,
assetId: this.assetId,
source: {
type: PeerType.VAULT_ACCOUNT,
id: this.params.vaultAccountId
},
note: txNote || '',
extraParameters: {
rawMessageData: {
messages: [{
content
}]
}
}
};
const { id, status } = await this.params.fireblocksApiClient.createTransaction(transactionParams);
let txInfo: TransactionResponse;
let currentStatus: TransactionStatus = <TransactionStatus>status;
while(!BaseBridge.finalTransactionStates.includes(currentStatus)) {
try {
txInfo = await this.params.fireblocksApiClient.getTransactionById(id);
currentStatus = txInfo.status;
} catch (err) {
console.log("error:" ,err);
}
await new Promise(r => setTimeout(r, 1000));
}
if(currentStatus != TransactionStatus.COMPLETED) {
throw new Error(`Transaction was not completed successfully. Final Status: ${currentStatus}`);
}
const sig = txInfo.signedMessages[0].signature;
const v = 27 + sig.v;
return "0x" + sig.r + sig.s + v.toString(16);
}
async sendTransaction(transaction: TransactionConfig, txNote?: string): Promise<CreateTransactionResponse> {
if (transaction.chainId && transaction.chainId != this.getChainId()) {
throw new Error(`Chain ID of the transaction (${transaction.chainId}) does not match the chain ID of the connected account (${this.getChainId()})`);
}
const txArguments: TransactionArguments = {
operation: TransactionOperation.CONTRACT_CALL,
assetId: this.assetId,
source: {
type: PeerType.VAULT_ACCOUNT,
id: this.params.vaultAccountId
},
destination: {
type: this.params.externalWalletId ? PeerType.EXTERNAL_WALLET : PeerType.ONE_TIME_ADDRESS,
id: this.params.externalWalletId,
},
note: txNote || '',
amount: formatEther(transaction.value?.toString() || "0"),
extraParameters: {
contractCallData: transaction.data
}
};
if (transaction.to) {
txArguments.destination.oneTimeAddress = {
address: <string>transaction.to
}
}
return this.params.fireblocksApiClient.createTransaction(txArguments);
}
}