-
Notifications
You must be signed in to change notification settings - Fork 284
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(sdk-coin-icp): transaction build added for ICP
TICKET: WIN-4248
- Loading branch information
1 parent
fa245c4
commit d67e95c
Showing
9 changed files
with
425 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
export interface IcpTransactionData { | ||
readonly senderAddress: string; | ||
readonly receiverAddress: string; | ||
readonly amount: string; | ||
readonly fee: string; | ||
readonly senderPublicKeyHex: string; | ||
readonly sequenceNumber: number; | ||
readonly transactionType: string; | ||
readonly expireTime: number; | ||
readonly coin: string; | ||
readonly id: string; | ||
} | ||
|
||
export enum IcpTransactionType { | ||
Transfer = 'Transfer', | ||
} | ||
|
||
export interface IcpNetworkIdentifier { | ||
blockchain: string; | ||
network: string; | ||
} | ||
|
||
export interface IcpPublicKey { | ||
hex_bytes: string; | ||
curve_type: string; | ||
} | ||
|
||
export interface IcpOperationIdentifier { | ||
index: number; | ||
} | ||
|
||
export interface IcpAccount { | ||
address: string; | ||
} | ||
|
||
export interface IcpCurrency { | ||
symbol: string; | ||
decimals: number; | ||
} | ||
|
||
export interface IcpAmount { | ||
value: string; | ||
currency: IcpCurrency; | ||
} | ||
|
||
export interface IcpOperation { | ||
operation_identifier: IcpOperationIdentifier; | ||
type: string; | ||
account: IcpAccount; | ||
amount: IcpAmount; | ||
} | ||
|
||
export interface IcpMetadata { | ||
created_at_time: number; | ||
memo: number; | ||
ingress_start: number; | ||
ingress_end: number; | ||
} | ||
|
||
export interface IcpTransaction { | ||
network_identifier: IcpNetworkIdentifier; | ||
public_keys: IcpPublicKey[]; | ||
operations: IcpOperation[]; | ||
metadata: IcpMetadata; | ||
} | ||
|
||
export interface IcpUnsignedTransaction { | ||
unsigned_transaction: string; | ||
payloads: IcpPayload[]; | ||
} | ||
|
||
export interface IcpPayload { | ||
account_identifier: IcpAccountIdentifier; | ||
hex_bytes: string; | ||
signature_type: string; | ||
} | ||
|
||
export interface IcpAccountIdentifier { | ||
address: string; | ||
} | ||
|
||
export interface IcpSignature { | ||
signing_payload: IcpPayload; | ||
signature_type: string; | ||
public_key: IcpPublicKey; | ||
hex_bytes: string; | ||
} | ||
|
||
export interface IcpCombineApiPayload { | ||
network_identifier: IcpNetworkIdentifier; | ||
unsigned_transaction: string; | ||
signatures: IcpSignature[]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import { BaseKey, BaseTransaction } from '@bitgo/sdk-core'; | ||
import { BaseCoin as CoinConfig } from '@bitgo/statics'; | ||
import { IcpTransactionData, IcpTransaction, IcpMetadata } from './iface'; | ||
import { Utils } from './utils'; | ||
|
||
export class Transaction extends BaseTransaction { | ||
protected IcpTransaction: IcpTransaction; | ||
protected IcpTransactionData: IcpTransactionData; | ||
constructor(_coinConfig: Readonly<CoinConfig>) { | ||
super(_coinConfig); | ||
} | ||
|
||
get icpTransaction(): IcpTransaction { | ||
return this.IcpTransaction; | ||
} | ||
|
||
setIcpTransaction(tx: IcpTransaction): void { | ||
this.IcpTransaction = tx; | ||
} | ||
|
||
/** @inheritdoc */ | ||
toJson(): IcpTransaction { | ||
if (!this.IcpTransactionData) { | ||
throw new Error('Transaction data is not set.'); | ||
} | ||
|
||
this.IcpTransaction = { | ||
network_identifier: Utils.getNetworkIdentifier(), | ||
public_keys: [ | ||
{ | ||
hex_bytes: this.IcpTransactionData.senderPublicKeyHex, | ||
curve_type: Utils.getCurveType(), | ||
}, | ||
], | ||
operations: [ | ||
{ | ||
operation_identifier: { index: 0 }, | ||
type: Utils.getTransactionType(), | ||
account: { address: this.IcpTransactionData.senderAddress }, | ||
amount: { | ||
value: `-${this.IcpTransactionData.amount}`, // Negative for sender | ||
currency: { symbol: this.IcpTransactionData.coin, decimals: Utils.getDecimalPrecision() }, | ||
}, | ||
}, | ||
{ | ||
operation_identifier: { index: 1 }, | ||
type: Utils.getTransactionType(), | ||
account: { address: this.IcpTransactionData.receiverAddress }, | ||
amount: { | ||
value: this.IcpTransactionData.amount, // Positive for receiver | ||
currency: { symbol: this.IcpTransactionData.coin, decimals: Utils.getDecimalPrecision() }, | ||
}, | ||
}, | ||
{ | ||
operation_identifier: { index: 2 }, | ||
type: Utils.getFeeType(), | ||
account: { address: this.IcpTransactionData.senderAddress }, | ||
amount: { | ||
value: `-${this.IcpTransactionData.fee}`, // FEE is negative | ||
currency: { symbol: this.IcpTransactionData.coin, decimals: Utils.getDecimalPrecision() }, | ||
}, | ||
}, | ||
], | ||
metadata: this.getMetaData(), | ||
}; | ||
|
||
return this.IcpTransaction; | ||
} | ||
|
||
getMetaData(): IcpMetadata { | ||
const currentTime = Date.now() * 1_000_000; | ||
if (this.IcpTransactionData.expireTime >= currentTime) { | ||
throw new Error('Invalid expire time'); | ||
} | ||
return { | ||
created_at_time: currentTime, | ||
memo: this.IcpTransactionData.sequenceNumber, | ||
ingress_start: currentTime, | ||
ingress_end: this.IcpTransactionData.expireTime, | ||
}; | ||
} | ||
|
||
/** @inheritdoc */ | ||
toBroadcastFormat() { | ||
throw new Error('Method not implemented.'); | ||
} | ||
|
||
/** @inheritdoc */ | ||
canSign(key: BaseKey): boolean { | ||
return true; | ||
} | ||
|
||
static parseRawTransaction(rawTransaction: string): IcpTransactionData { | ||
try { | ||
const parsedTx = JSON.parse(rawTransaction); | ||
return { | ||
senderAddress: parsedTx.address, | ||
receiverAddress: parsedTx.externalOutputs[0].address, | ||
amount: parsedTx.inputAmount, | ||
fee: parsedTx.fee, //TODO: check if this is correct | ||
senderPublicKeyHex: parsedTx.senderPublicKey, | ||
sequenceNumber: parsedTx.seqno, | ||
transactionType: parsedTx.type, | ||
expireTime: parsedTx.expireTime, | ||
id: parsedTx.id, | ||
coin: parsedTx.coin, | ||
}; | ||
} catch (error) { | ||
throw new Error('Invalid raw transaction format: ' + error.message); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.