Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cleanup fireblocks signer #100

Merged
merged 5 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,619 changes: 1,501 additions & 2,118 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

69 changes: 38 additions & 31 deletions src/integrations/fb_signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
CreateTransactionResponse,
FireblocksSDK,
PeerType,
SigningAlgorithm,
TransactionArguments,
TransactionOperation,
TransactionResponse,
Expand Down Expand Up @@ -47,7 +46,7 @@ export class FbSigner {

/**
* Wait for given transaction to be completed
* @param fbTx: fireblocks transaction
* @param fbTx fireblocks transaction
* @private
*/
protected async waitForTxCompletion(fbTx: CreateTransactionResponse): Promise<TransactionResponse> {
Expand Down Expand Up @@ -76,19 +75,25 @@ export class FbSigner {

/**
* Sign a transaction with fireblocks using Fireblocks raw message signing feature
* @param payloadToSign: transaction data in hexadecimal
* @param assetId: fireblocks asset id
* @param note: optional fireblocks custom note
* @param payloadToSign transaction data in hexadecimal
* @param assetId fireblocks asset id
* @param note optional fireblocks custom note
*/
public async signWithFB(payloadToSign: any, assetId: AssetId, note?: string): Promise<TransactionResponse> {
public async sign(payloadToSign: any, assetId?: AssetId, note?: string): Promise<TransactionResponse> {
try {
const assetArgs = assetId
? {
assetId,
source: {
type: PeerType.VAULT_ACCOUNT,
id: this.vaultId.toString(),
},
}
: {};

const tx: TransactionArguments = {
assetId: assetId,
...assetArgs,
operation: TransactionOperation.RAW,
source: {
type: PeerType.VAULT_ACCOUNT,
id: this.vaultId.toString(),
},
note,
extraParameters: payloadToSign,
};
Expand All @@ -101,52 +106,54 @@ export class FbSigner {
}

/**
* Sign a generic transaction with fireblocks using Fireblocks raw message signing feature.
* @param payloadToSign: transaction data in hexadecimal
* @param derivationPath: derivation path of the token to sign
* @param algorithm: algorithm of the token to sign
* @param note: optional fireblocks custom note
* Sign an EIP-712 Ethereum typed message with fireblocks
* @param eip712message eip712message to sign
* @param assetId fireblocks asset id
* @param note optional fireblocks custom note
*/
public async signGenericWithFB(
payloadContent: string,
derivationPath: number[],
algorithm: SigningAlgorithm,
public async signTypedMessage(
goulinkh marked this conversation as resolved.
Show resolved Hide resolved
eip712message: any,
assetId: "ETH" | "ETH_TEST3" | "ETH_TEST6",
note?: string,
): Promise<TransactionResponse> {
try {
const payloadToSign = {
operation: TransactionOperation.RAW,
const tx: TransactionArguments = {
assetId: assetId,
operation: TransactionOperation.TYPED_MESSAGE,
source: {
type: PeerType.VAULT_ACCOUNT,
id: this.vaultId.toString(),
},
note,
extraParameters: {
rawMessageData: {
messages: [
{
content: payloadContent,
derivationPath,
content: eip712message,
type: "EIP712",
},
],
algorithm,
},
},
};
const fbTx = await this.fireblocks.createTransaction(payloadToSign);
const fbTx = await this.fireblocks.createTransaction(tx);
return await this.waitForTxCompletion(fbTx);
} catch (err: any) {
console.log(err);
throw new Error("Fireblocks signer (signGenericWithFB): " + err);
throw new Error("Fireblocks signer (signWithFB): " + err);
}
}

/**
* Sign and broadcast a transaction with fireblocks using Fireblocks contract call feature
* @param payloadToSign: transaction data in hexadecimal
* @param assetId: fireblocks asset id
* @param note: optional fireblocks custom note
* @param payloadToSign transaction data in hexadecimal
* @param assetId fireblocks asset id
* @param note optional fireblocks custom note
* @param tx Ethereum transaction
* @param destinationId Fireblocks destination id, this corresponds to the Fireblocks whitelisted contract address id
* @param sendAmount send the amount in tx to smart contract
*/
public async signAndBroadcastWithFB(
public async signAndBroadcastWith(
payloadToSign: any,
assetId: AssetId,
tx: EthTx | MaticTx,
Expand Down
2 changes: 1 addition & 1 deletion src/services/ada.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export class AdaService extends Service {
};

const fbNote = note ? note : "ADA tx from @kilnfi/sdk";
const fbTx = await fbSigner.signWithFB(payload, this.testnet ? "ADA_TEST" : "ADA", fbNote);
const fbTx = await fbSigner.sign(payload, this.testnet ? "ADA_TEST" : "ADA", fbNote);

if (!fbTx.signedMessages) {
throw new Error(`Could not sign the transaction.`);
Expand Down
3 changes: 1 addition & 2 deletions src/services/atom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ export class AtomService extends Service {
/**
* Craft atom restake rewards transaction
* @param pubkey wallet pubkey, this is different from the wallet address
* @param validatorAccount validator account address (wallet controlling the validator)
* @param validatorAddress validator address to which the delegation has been made
*/
async craftRestakeRewardsTx(pubkey: string, validatorAddress: string): Promise<CosmosTx> {
Expand Down Expand Up @@ -131,7 +130,7 @@ export class AtomService extends Service {
};
const fbNote = note ? note : "ATOM tx from @kilnfi/sdk";
const signer = this.getFbSigner(integration);
const fbTx = await signer.signWithFB(payload, this.testnet ? "ATOM_COS_TEST" : "ATOM_COS", fbNote);
const fbTx = await signer.sign(payload, this.testnet ? "ATOM_COS_TEST" : "ATOM_COS", fbNote);
const signature: string = fbTx.signedMessages![0].signature.fullSig;
const { data } = await api.post<CosmosSignedTx>(`/v1/atom/transaction/prepare`, {
pubkey: tx.data.pubkey,
Expand Down
2 changes: 1 addition & 1 deletion src/services/dot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ export class DotService extends Service {

const fbSigner = this.getFbSigner(integration);
const fbNote = note ? note : "DOT tx from @kilnfi/sdk";
const fbTx = await fbSigner.signWithFB(payload, this.testnet ? "WND" : "DOT", fbNote);
const fbTx = await fbSigner.sign(payload, this.testnet ? "WND" : "DOT", fbNote);
const signature = `0x00${fbTx.signedMessages![0].signature.fullSig}`;

const { data } = await api.post<DotSignedTx>(`/v1/dot/transaction/prepare`, {
Expand Down
2 changes: 1 addition & 1 deletion src/services/dydx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export class DydxService extends Service {
};
const fbNote = note ? note : "DYDX tx from @kilnfi/sdk";
const signer = this.getFbSigner(integration);
const fbTx = await signer.signWithFB(payload, "DYDX_DYDX", fbNote);
const fbTx = await signer.sign(payload, "DYDX_DYDX", fbNote);
const signature: string = fbTx.signedMessages![0].signature.fullSig;
const { data } = await api.post<CosmosSignedTx>(`/v1/dydx/transaction/prepare`, {
pubkey: tx.data.pubkey,
Expand Down
11 changes: 2 additions & 9 deletions src/services/eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class EthService extends Service {
const fbSigner = this.getFbSigner(integration);
const assetId = this.testnet ? "ETH_TEST6" : "ETH";
const fbNote = note ? note : "ETH tx from @kilnfi/sdk";
const fbTx = await fbSigner.signWithFB(payload, assetId, fbNote);
const fbTx = await fbSigner.sign(payload, assetId, fbNote);
const { data } = await api.post<EthSignedTx>(`/v1/eth/transaction/prepare`, {
unsigned_tx_serialized: tx.data.unsigned_tx_serialized,
r: `0x${fbTx?.signedMessages?.[0].signature.r}`,
Expand Down Expand Up @@ -98,14 +98,7 @@ export class EthService extends Service {
const fbSigner = this.getFbSigner(integration);
const assetId = this.testnet ? "ETH_TEST6" : "ETH";
const fbNote = note ? note : "ETH tx from @kilnfi/sdk";
return await fbSigner.signAndBroadcastWithFB(
payload,
assetId,
tx,
integration.fireblocksDestinationId,
true,
fbNote,
);
return await fbSigner.signAndBroadcastWith(payload, assetId, tx, integration.fireblocksDestinationId, true, fbNote);
}

/**
Expand Down
18 changes: 12 additions & 6 deletions src/services/fet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ export class FetService extends Service {
/**
* Craft fetch.ai restake rewards transaction
* @param pubkey wallet pubkey, this is different from the wallet address
* @param validatorAccount validator account address (wallet controlling the validator)
* @param validatorAddress validator address to which the delegation has been made
*/
async craftRestakeRewardsTx(pubkey: string, validatorAddress: string): Promise<CosmosTx> {
Expand Down Expand Up @@ -120,13 +119,20 @@ export class FetService extends Service {
* @param note note to identify the transaction in your custody solution
*/
async sign(integration: Integration, tx: CosmosTx, note?: string): Promise<CosmosSignedTx> {
const payloadContent = tx.data.unsigned_tx_hash;
const derivationPath = [44, 118, integration.vaultId, 0, 0];
const signingAlgorithm = SigningAlgorithm.MPC_ECDSA_SECP256K1;
const fbNote = note ? note : "FET tx from @kilnfi/sdk";

const signer = this.getFbSigner(integration);
const fbTx = await signer.signGenericWithFB(payloadContent, derivationPath, signingAlgorithm, fbNote);
const payload = {
rawMessageData: {
messages: [
{
content: tx.data.unsigned_tx_hash,
derivationPath: [44, 118, integration.vaultId, 0, 0],
},
],
algorithm: SigningAlgorithm.MPC_ECDSA_SECP256K1,
},
};
const fbTx = await signer.sign(payload, undefined, fbNote);
const signature: string = fbTx.signedMessages![0].signature.fullSig;
const { data } = await api.post<CosmosSignedTx>(`/v1/fet/transaction/prepare`, {
pubkey: tx.data.pubkey,
Expand Down
3 changes: 1 addition & 2 deletions src/services/inj.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ export class InjService extends Service {
/**
* Craft inj restake rewards transaction
* @param pubkey wallet pubkey, this is different from the wallet address
* @param validatorAccount validator account address (wallet controlling the validator)
* @param validatorAddress validator address to which the delegation has been made
*/
async craftRestakeRewardsTx(pubkey: string, validatorAddress: string): Promise<CosmosTx> {
Expand Down Expand Up @@ -130,7 +129,7 @@ export class InjService extends Service {
};
const fbNote = note ? note : "INJ tx from @kilnfi/sdk";
const signer = this.getFbSigner(integration);
const fbTx = await signer.signWithFB(payload, "INJ_INJ", fbNote);
const fbTx = await signer.sign(payload, "INJ_INJ", fbNote);
const signature: string = fbTx.signedMessages![0].signature.fullSig;
const { data } = await api.post<CosmosSignedTx>(`/v1/inj/transaction/prepare`, {
pubkey: tx.data.pubkey,
Expand Down
4 changes: 2 additions & 2 deletions src/services/matic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export class MaticService extends Service {

const fbSigner = this.getFbSigner(integration);
const fbNote = note ? note : "MATIC tx from @kilnfi/sdk";
const fbTx = await fbSigner.signWithFB(payload, this.testnet ? "ETH_TEST3" : "ETH", fbNote);
const fbTx = await fbSigner.sign(payload, this.testnet ? "ETH_TEST3" : "ETH", fbNote);
const { data } = await api.post<MaticSignedTx>(`/v1/matic/transaction/prepare`, {
unsigned_tx_serialized: tx.data.unsigned_tx_serialized,
r: `0x${fbTx?.signedMessages?.[0].signature.r}`,
Expand Down Expand Up @@ -164,7 +164,7 @@ export class MaticService extends Service {
const fbSigner = this.getFbSigner(integration);
const fbNote = note ? note : "MATIC tx from @kilnfi/sdk";
const assetId = this.testnet ? "ETH_TEST3" : "ETH";
return await fbSigner.signAndBroadcastWithFB(
return await fbSigner.signAndBroadcastWith(
payload,
assetId,
tx,
Expand Down
2 changes: 1 addition & 1 deletion src/services/near.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export class NearService extends Service {

const fbSigner = this.getFbSigner(integration);
const fbNote = note ? note : "NEAR tx from @kilnfi/sdk";
const fbTx = await fbSigner.signWithFB(payload, this.testnet ? "NEAR_TEST" : "NEAR", fbNote);
const fbTx = await fbSigner.sign(payload, this.testnet ? "NEAR_TEST" : "NEAR", fbNote);
const signature = fbTx.signedMessages![0];

const signedTx = new transactions.SignedTransaction({
Expand Down
2 changes: 1 addition & 1 deletion src/services/noble.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class NobleService extends Service {
const fbNote = note ? note : "NOBLE tx from @kilnfi/sdk";
const signer = this.getFbSigner(integration);
// NOBLE chain is not supported by Fireblocks, so we use DYDX_DYDX
const fbTx = await signer.signWithFB(payload, "DYDX_DYDX", fbNote);
const fbTx = await signer.sign(payload, "DYDX_DYDX", fbNote);
const signature: string = fbTx.signedMessages![0].signature.fullSig;
const { data } = await api.post<CosmosSignedTx>(`/v1/noble/transaction/prepare`, {
pubkey: tx.data.pubkey,
Expand Down
3 changes: 1 addition & 2 deletions src/services/osmo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ export class OsmoService extends Service {
/**
* Craft osmo restake rewards transaction
* @param pubkey wallet pubkey, this is different from the wallet address
* @param validatorAccount validator account address (wallet controlling the validator)
* @param validatorAddress validator address to which the delegation has been made
*/
async craftRestakeRewardsTx(pubkey: string, validatorAddress: string): Promise<CosmosTx> {
Expand Down Expand Up @@ -131,7 +130,7 @@ export class OsmoService extends Service {
};
const fbNote = note ? note : "OSMO tx from @kilnfi/sdk";
const signer = this.getFbSigner(integration);
const fbTx = await signer.signWithFB(payload, "OSMO", fbNote);
const fbTx = await signer.sign(payload, "OSMO", fbNote);
const signature: string = fbTx.signedMessages![0].signature.fullSig;
const { data } = await api.post<CosmosSignedTx>(`/v1/osmo/transaction/prepare`, {
pubkey: tx.data.pubkey,
Expand Down
2 changes: 1 addition & 1 deletion src/services/sol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export class SolService extends Service {

const fbSigner = this.getFbSigner(integration);
const fbNote = note ? note : "SOL tx from @kilnfi/sdk";
const fbTx = await fbSigner.signWithFB(payload, this.testnet ? "SOL_TEST" : "SOL", fbNote);
const fbTx = await fbSigner.sign(payload, this.testnet ? "SOL_TEST" : "SOL", fbNote);
const signatures: string[] = [];
fbTx.signedMessages?.forEach((signedMessage: any) => {
if (signedMessage.derivationPath[3] == 0) {
Expand Down
3 changes: 1 addition & 2 deletions src/services/tia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ export class TiaService extends Service {
/**
* Craft tia restake rewards transaction
* @param pubkey wallet pubkey, this is different from the wallet address
* @param validatorAccount validator account address (wallet controlling the validator)
* @param validatorAddress validator address to which the delegation has been made
*/
async craftRestakeRewardsTx(pubkey: string, validatorAddress: string): Promise<CosmosTx> {
Expand Down Expand Up @@ -130,7 +129,7 @@ export class TiaService extends Service {
};
const fbNote = note ? note : "TIA tx from @kilnfi/sdk";
const signer = this.getFbSigner(integration);
const fbTx = await signer.signWithFB(payload, "CELESTIA", fbNote);
const fbTx = await signer.sign(payload, "CELESTIA", fbNote);
const signature: string = fbTx.signedMessages![0].signature.fullSig;
const { data } = await api.post<CosmosSignedTx>(`/v1/tia/transaction/prepare`, {
pubkey: tx.data.pubkey,
Expand Down
2 changes: 1 addition & 1 deletion src/services/xtz.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class XtzService extends Service {

const fbSigner = this.getFbSigner(integration);
const fbNote = note ? note : "XTZ tx from @kilnfi/sdk";
const fbTx = await fbSigner.signWithFB(payload, this.testnet ? "XTZ_TEST" : "XTZ", fbNote);
const fbTx = await fbSigner.sign(payload, this.testnet ? "XTZ_TEST" : "XTZ", fbNote);
const signature: string = fbTx.signedMessages![0].signature.fullSig;
const { data } = await api.post<XtzSignedTx>(`/v1/xtz/transaction/prepare`, {
unsigned_tx_serialized: tx.data.unsigned_tx_serialized,
Expand Down
Loading