parent
66d558c813
commit
b1ca749fb7
@ -0,0 +1,17 @@ |
||||
import { Transaction, TxParams } from '@harmony/transaction'; |
||||
import { sign, keccak256, Signature } from '@harmony/crypto'; |
||||
|
||||
export const RLPSign = ( |
||||
transaction: Transaction, |
||||
prv: string, |
||||
): [Signature, string] => { |
||||
const [unsignedTxnHash, raw] = transaction.getRLPUnsigned(); |
||||
const regroup: TxParams = { |
||||
...transaction.txParams, |
||||
unsignedTxnHash, |
||||
}; |
||||
transaction.setParams(regroup); |
||||
const signature = sign(keccak256(unsignedTxnHash), prv); |
||||
const signed = transaction.getRLPSigned(raw, signature); |
||||
return [signature, signed]; |
||||
}; |
@ -1,12 +1,16 @@ |
||||
import hdkey from 'hdkey'; |
||||
import bip39 from 'bip39'; |
||||
import BN from 'bn.js'; |
||||
|
||||
export * from './random'; |
||||
export * from './keyTool'; |
||||
export * from './keystore'; |
||||
export * from './bytes'; |
||||
export * from './rlp'; |
||||
export * from './keccak256'; |
||||
export * from './errors'; |
||||
|
||||
// export types
|
||||
export * from './types'; |
||||
|
||||
export { hdkey, bip39 }; |
||||
export { hdkey, bip39, BN }; |
||||
|
@ -1,2 +1,3 @@ |
||||
export * from './factory'; |
||||
export * from './transaction'; |
||||
export * from './types'; |
||||
|
@ -1,2 +1,158 @@ |
||||
class Transaction {} |
||||
import { |
||||
BN, |
||||
encode, |
||||
// toChecksumAddress,
|
||||
arrayify, |
||||
hexlify, |
||||
stripZeros, |
||||
Signature, |
||||
splitSignature, |
||||
} from '@harmony/crypto'; |
||||
import { add0xToString } from '@harmony/utils'; |
||||
import { TxParams } from './types'; |
||||
|
||||
export const transactionFields = [ |
||||
{ name: 'nonce', length: 32, fix: false }, |
||||
{ name: 'gasPrice', length: 32, fix: false, transform: 'hex' }, |
||||
{ name: 'gasLimit', length: 32, fix: false, transform: 'hex' }, |
||||
{ name: 'to', length: 20, fix: true }, |
||||
{ name: 'value', length: 32, fix: false, transform: 'hex' }, |
||||
{ name: 'data', fix: false }, |
||||
]; |
||||
|
||||
class Transaction { |
||||
// private hash?: string;
|
||||
// private from?: string;
|
||||
private nonce: number | string; |
||||
private to: string; |
||||
private gasLimit: BN; |
||||
private gasPrice: BN; |
||||
private data: string; |
||||
private value: BN; |
||||
private chainId: number; |
||||
private txnHash: string; |
||||
private unsignedTxnHash: string; |
||||
private signature: Signature; |
||||
// private r?: string;
|
||||
// private s?: string;
|
||||
// private v?: number;
|
||||
// constructor
|
||||
constructor(params?: TxParams) { |
||||
this.nonce = params ? params.nonce : 0; |
||||
this.gasPrice = params ? params.gasPrice : new BN(0); |
||||
this.gasLimit = params ? params.gasLimit : new BN(0); |
||||
this.to = params ? params.to : '0x'; |
||||
this.value = params ? params.value : new BN(0); |
||||
this.data = params ? params.data : '0x'; |
||||
this.chainId = params ? params.chainId : 0; |
||||
this.txnHash = params ? params.txnHash : '0x'; |
||||
this.unsignedTxnHash = params ? params.unsignedTxnHash : '0x'; |
||||
this.signature = params |
||||
? params.signature |
||||
: { |
||||
r: '', |
||||
s: '', |
||||
recoveryParam: 0, |
||||
v: 0, |
||||
}; |
||||
} |
||||
|
||||
getRLPUnsigned(): [string, any[]] { |
||||
const raw: Array<string | Uint8Array> = []; |
||||
|
||||
transactionFields.forEach((field: any) => { |
||||
let value = (<any>this.txParams)[field.name] || []; |
||||
value = arrayify( |
||||
hexlify( |
||||
field.transform === 'hex' |
||||
? add0xToString(value.toString('hex')) |
||||
: value, |
||||
), |
||||
); |
||||
// Fixed-width field
|
||||
if ( |
||||
field.fix === true && |
||||
field.length && |
||||
value.length !== field.length && |
||||
value.length > 0 |
||||
) { |
||||
throw new Error(`invalid length for ${field.name}`); |
||||
} |
||||
|
||||
// Variable-width (with a maximum)
|
||||
if (field.fix === false && field.length) { |
||||
value = stripZeros(value); |
||||
if (value.length > field.length) { |
||||
throw new Error(`invalid length for ${field.name}`); |
||||
} |
||||
} |
||||
|
||||
raw.push(hexlify(value)); |
||||
}); |
||||
|
||||
if (this.txParams.chainId != null && this.txParams.chainId !== 0) { |
||||
raw.push(hexlify(this.txParams.chainId)); |
||||
raw.push('0x'); |
||||
raw.push('0x'); |
||||
} |
||||
|
||||
return [encode(raw), raw]; |
||||
} |
||||
|
||||
getRLPSigned(raw: any[], signature: Signature): string { |
||||
const sig = splitSignature(signature); |
||||
let v = 27 + (sig.recoveryParam || 0); |
||||
if (raw.length === 9) { |
||||
raw.pop(); |
||||
raw.pop(); |
||||
raw.pop(); |
||||
v += this.chainId * 2 + 8; |
||||
} |
||||
|
||||
raw.push(hexlify(v)); |
||||
raw.push(stripZeros(arrayify(sig.r) || [])); |
||||
raw.push(stripZeros(arrayify(sig.s) || [])); |
||||
|
||||
return encode(raw); |
||||
} |
||||
get txParams(): TxParams { |
||||
return { |
||||
nonce: this.nonce || 0, |
||||
gasPrice: this.gasPrice || new BN(0), |
||||
gasLimit: this.gasLimit || new BN(0), |
||||
to: this.to || '0x', |
||||
value: this.value || new BN(0), |
||||
data: this.data || '0x', |
||||
chainId: this.chainId || 0, |
||||
txnHash: this.txnHash || '0x', |
||||
unsignedTxnHash: this.unsignedTxnHash || '0x', |
||||
signature: this.signature || '0x', |
||||
}; |
||||
} |
||||
setParams(params: TxParams) { |
||||
this.nonce = params ? params.nonce : 0; |
||||
this.gasPrice = params ? params.gasPrice : new BN(0); |
||||
this.gasLimit = params ? params.gasLimit : new BN(0); |
||||
this.to = params ? params.to : '0x'; |
||||
this.value = params ? params.value : new BN(0); |
||||
this.data = params ? params.data : '0x'; |
||||
this.chainId = params ? params.chainId : 0; |
||||
this.txnHash = params ? params.txnHash : '0x'; |
||||
this.unsignedTxnHash = params ? params.unsignedTxnHash : '0x'; |
||||
this.signature = params |
||||
? params.signature |
||||
: { |
||||
r: '', |
||||
s: '', |
||||
recoveryParam: 0, |
||||
v: 0, |
||||
}; |
||||
} |
||||
|
||||
map(fn: any) { |
||||
const newParams = fn(this.txParams); |
||||
this.setParams(newParams); |
||||
return this; |
||||
} |
||||
} |
||||
export { Transaction }; |
||||
|
@ -0,0 +1,13 @@ |
||||
import { BN, Signature } from '@harmony/crypto'; |
||||
export interface TxParams { |
||||
to: string; |
||||
nonce: number | string; |
||||
gasLimit: BN; |
||||
gasPrice: BN; |
||||
data: string; |
||||
value: BN; |
||||
chainId: number; |
||||
txnHash: string; |
||||
unsignedTxnHash: string; |
||||
signature: Signature; |
||||
} |
Loading…
Reference in new issue