@arkecosystem/typescript-crypto 0.0.9 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +11,7 @@ export declare class PrivateKey {
11
11
  static fromHex(hex: string): PrivateKey;
12
12
  static fromWif(wif: string): PrivateKey;
13
13
  sign(message: string): Promise<RecoverableSignature>;
14
+ signToEcdsa(message: string): Promise<string>;
14
15
  }
15
16
  export {};
16
17
  //# sourceMappingURL=PrivateKey.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PrivateKey.d.ts","sourceRoot":"","sources":["../../src/identities/PrivateKey.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAkC,MAAM,QAAQ,CAAC;AAMhE,UAAU,oBAAoB;IAC7B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACV;AAED,qBAAa,UAAU;IACf,UAAU,EAAE,MAAM,CAAC;gBAEd,OAAO,EAAE,MAAM,CAAC,MAAM;IAIlC,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU;IAIrD,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAMvC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAMjC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAW1D"}
1
+ {"version":3,"file":"PrivateKey.d.ts","sourceRoot":"","sources":["../../src/identities/PrivateKey.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAkC,MAAM,QAAQ,CAAC;AAMhE,UAAU,oBAAoB;IAC7B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACV;AAED,qBAAa,UAAU;IACf,UAAU,EAAE,MAAM,CAAC;gBAEd,OAAO,EAAE,MAAM,CAAC,MAAM;IAIlC,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU;IAIrD,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAMvC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAMjC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAWpD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAQnD"}
@@ -38,4 +38,13 @@ export class PrivateKey {
38
38
  };
39
39
  });
40
40
  }
41
+ signToEcdsa(message) {
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ const hash = keccak256("0x" + message).slice(2);
44
+ const signature = yield signAsync(hash, this.privateKey);
45
+ const v = signature.recovery + Constants.ETHEREUM_RECOVERY_ID_OFFSET;
46
+ // @see https://github.com/ArkEcosystem/mainsail/blob/16e50d45dcfbf15b20245f11b123634f0fd0b713/packages/utils/source/format-ecdsa-signature.ts#L2
47
+ return signature.toCompactHex() + v.toString(16).padStart(2, "0");
48
+ });
49
+ }
41
50
  }
package/dist/index.js CHANGED
@@ -23528,6 +23528,12 @@ var PrivateKey = class _PrivateKey {
23528
23528
  v: signature.recovery + 27 /* ETHEREUM_RECOVERY_ID_OFFSET */
23529
23529
  };
23530
23530
  }
23531
+ async signToEcdsa(message) {
23532
+ const hash2 = keccak256("0x" + message).slice(2);
23533
+ const signature = await signAsync(hash2, this.privateKey);
23534
+ const v = signature.recovery + 27 /* ETHEREUM_RECOVERY_ID_OFFSET */;
23535
+ return signature.toCompactHex() + v.toString(16).padStart(2, "0");
23536
+ }
23531
23537
  };
23532
23538
 
23533
23539
  // src/identities/PublicKey.ts
@@ -24965,6 +24971,11 @@ var AbstractTransactionBuilder = class {
24965
24971
  this.transaction.data.hash = this.transaction.hash();
24966
24972
  return this;
24967
24973
  }
24974
+ async legacySecondSign(passphrase, secondPassprase) {
24975
+ await this.sign(passphrase);
24976
+ this.transaction = await this.transaction.legacySecondSign(PrivateKey.fromPassphrase(secondPassprase));
24977
+ return this;
24978
+ }
24968
24979
  verify() {
24969
24980
  return this.transaction.verify();
24970
24981
  }
@@ -24997,6 +25008,9 @@ var TransactionUtils = class {
24997
25008
  fields.push(toBeArray(transaction["v"] - 27 /* ETHEREUM_RECOVERY_ID_OFFSET */));
24998
25009
  fields.push("0x" + transaction["r"]);
24999
25010
  fields.push("0x" + transaction["s"]);
25011
+ if (transaction.legacySecondSignature) {
25012
+ fields.push(`0x${transaction.legacySecondSignature}`);
25013
+ }
25000
25014
  }
25001
25015
  const encoded = encodeRlp(fields);
25002
25016
  const payload = "02" /* EIP_1559_PREFIX */ + encoded.substring(2);
@@ -25040,6 +25054,11 @@ var AbstractTransaction = class {
25040
25054
  this.data["s"] = signature.s;
25041
25055
  return this;
25042
25056
  }
25057
+ async legacySecondSign(privateKey) {
25058
+ const hash2 = TransactionUtils.toBuffer(this.data, true).toString("hex");
25059
+ this.data.legacySecondSignature = await privateKey.signToEcdsa(hash2);
25060
+ return this;
25061
+ }
25043
25062
  recoverSender() {
25044
25063
  const publicKey = this.recoverPublicKey();
25045
25064
  this.data["senderPublicKey"] = publicKey.publicKey;
@@ -25061,6 +25080,7 @@ var AbstractTransaction = class {
25061
25080
  "gas",
25062
25081
  "nonce",
25063
25082
  "senderPublicKey",
25083
+ "legacySecondSignature",
25064
25084
  "to",
25065
25085
  "value",
25066
25086
  "data",
@@ -9,6 +9,7 @@ export declare abstract class AbstractTransactionBuilder<T extends ITransactionB
9
9
  nonce(nonce: string): T;
10
10
  network(network: number): T;
11
11
  sign(passphrase: string): Promise<T>;
12
+ legacySecondSign(passphrase: string, secondPassprase: string): Promise<T>;
12
13
  verify(): boolean;
13
14
  toObject(): TransactionData;
14
15
  toJson(): string;
@@ -1 +1 @@
1
- {"version":3,"file":"AbstractTransactionBuilder.d.ts","sourceRoot":"","sources":["../../../src/transactions/builders/AbstractTransactionBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK7E,OAAO,SAAS,MAAM,cAAc,CAAC;AAErC,8BAAsB,0BAA0B,CAAC,CAAC,SAAS,mBAAmB,CAAC,CAAC,CAAC,CAAE,YAAW,mBAAmB,CAAC,CAAC,CAAC;IAC5G,WAAW,EAAE,YAAY,CAAC;gBAErB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAcnC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,CAAC;IAU/B,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,CAAC;IAMjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,CAAC;IAUzC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC;IAMvB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC;IAMrB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAU1C,MAAM,IAAI,OAAO;IAIjB,QAAQ,IAAI,eAAe;IAI3B,MAAM,IAAI,MAAM;IAIhB,QAAQ,IAAI,MAAM;IAIzB,SAAS,CAAC,QAAQ,CAAC,sBAAsB,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY;CACvF"}
1
+ {"version":3,"file":"AbstractTransactionBuilder.d.ts","sourceRoot":"","sources":["../../../src/transactions/builders/AbstractTransactionBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK7E,OAAO,SAAS,MAAM,cAAc,CAAC;AAErC,8BAAsB,0BAA0B,CAAC,CAAC,SAAS,mBAAmB,CAAC,CAAC,CAAC,CAAE,YAAW,mBAAmB,CAAC,CAAC,CAAC;IAC5G,WAAW,EAAE,YAAY,CAAC;gBAErB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAcnC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,CAAC;IAU/B,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,CAAC;IAMjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,CAAC;IAUzC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC;IAMvB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC;IAMrB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAUpC,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAQ/E,MAAM,IAAI,OAAO;IAIjB,QAAQ,IAAI,eAAe;IAI3B,MAAM,IAAI,MAAM;IAIhB,QAAQ,IAAI,MAAM;IAIzB,SAAS,CAAC,QAAQ,CAAC,sBAAsB,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY;CACvF"}
@@ -57,6 +57,13 @@ export class AbstractTransactionBuilder {
57
57
  return this;
58
58
  });
59
59
  }
60
+ legacySecondSign(passphrase, secondPassprase) {
61
+ return __awaiter(this, void 0, void 0, function* () {
62
+ yield this.sign(passphrase);
63
+ this.transaction = yield this.transaction.legacySecondSign(PrivateKey.fromPassphrase(secondPassprase));
64
+ return this;
65
+ });
66
+ }
60
67
  verify() {
61
68
  return this.transaction.verify();
62
69
  }
@@ -8,6 +8,7 @@ export declare abstract class AbstractTransaction implements ITransaction {
8
8
  abstract getPayload(): string;
9
9
  refreshPayloadData(): ITransaction;
10
10
  sign(privateKey: PrivateKey): Promise<ITransaction>;
11
+ legacySecondSign(privateKey: PrivateKey): Promise<ITransaction>;
11
12
  recoverSender(): void;
12
13
  verify(): boolean;
13
14
  toObject(): TransactionData;
@@ -1 +1 @@
1
- {"version":3,"file":"AbstractTransaction.d.ts","sourceRoot":"","sources":["../../../src/transactions/types/AbstractTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAIxD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAKnD,8BAAsB,mBAAoB,YAAW,YAAY;IACzD,IAAI,EAAE,eAAe,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEnB,IAAI,EAAE,eAAe;aAMxB,UAAU,IAAI,MAAM;IAE7B,kBAAkB,IAAI,YAAY;IAM5B,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IAYzD,aAAa,IAAI,IAAI;IAOrB,MAAM,IAAI,OAAO;IAWjB,QAAQ,IAAI,eAAe;IA4B3B,MAAM,IAAI,MAAM;IAIhB,IAAI,CAAC,aAAa,UAAQ,GAAG,MAAM;IAInC,SAAS,CAAC,aAAa,UAAQ,GAAG,MAAM;IAI/C,SAAS,CAAC,gBAAgB,IAAI,SAAS;CAYvC"}
1
+ {"version":3,"file":"AbstractTransaction.d.ts","sourceRoot":"","sources":["../../../src/transactions/types/AbstractTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAIxD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAKnD,8BAAsB,mBAAoB,YAAW,YAAY;IACzD,IAAI,EAAE,eAAe,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEnB,IAAI,EAAE,eAAe;aAMxB,UAAU,IAAI,MAAM;IAE7B,kBAAkB,IAAI,YAAY;IAM5B,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IAYnD,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IAQrE,aAAa,IAAI,IAAI;IAOrB,MAAM,IAAI,OAAO;IAWjB,QAAQ,IAAI,eAAe;IA6B3B,MAAM,IAAI,MAAM;IAIhB,IAAI,CAAC,aAAa,UAAQ,GAAG,MAAM;IAInC,SAAS,CAAC,aAAa,UAAQ,GAAG,MAAM;IAI/C,SAAS,CAAC,gBAAgB,IAAI,SAAS;CAYvC"}
@@ -32,6 +32,13 @@ export class AbstractTransaction {
32
32
  return this;
33
33
  });
34
34
  }
35
+ legacySecondSign(privateKey) {
36
+ return __awaiter(this, void 0, void 0, function* () {
37
+ const hash = TransactionUtils.toBuffer(this.data, true).toString("hex");
38
+ this.data.legacySecondSignature = yield privateKey.signToEcdsa(hash);
39
+ return this;
40
+ });
41
+ }
35
42
  recoverSender() {
36
43
  const publicKey = this.recoverPublicKey();
37
44
  this.data["senderPublicKey"] = publicKey.publicKey;
@@ -53,6 +60,7 @@ export class AbstractTransaction {
53
60
  "gas",
54
61
  "nonce",
55
62
  "senderPublicKey",
63
+ "legacySecondSignature",
56
64
  "to",
57
65
  "value",
58
66
  "data",
package/dist/types.d.ts CHANGED
@@ -3,6 +3,7 @@ import { Result } from "ethers";
3
3
  export interface TransactionData {
4
4
  gasPrice?: string | null;
5
5
  network?: number | string | null;
6
+ legacySecondSignature?: number | string | null;
6
7
  hash?: string | null;
7
8
  gas?: string | null;
8
9
  nonce?: number | string | null;
@@ -30,6 +31,7 @@ export interface ITransaction {
30
31
  getPayload(): string;
31
32
  refreshPayloadData(): ITransaction;
32
33
  sign(privateKey: unknown): Promise<ITransaction>;
34
+ legacySecondSign(privateKey: unknown): Promise<ITransaction>;
33
35
  recoverSender(): void;
34
36
  verify(): boolean;
35
37
  toObject(): TransactionData;
@@ -45,6 +47,7 @@ export interface ITransactionBuilder<T extends ITransactionBuilder<T>> {
45
47
  nonce(nonce: string): T;
46
48
  network(network: number): T;
47
49
  sign(passphrase: string): Promise<T>;
50
+ legacySecondSign(passphrase: string, secondPassphrase: string): Promise<T>;
48
51
  verify(): boolean;
49
52
  toObject(): TransactionData;
50
53
  toJson(): string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACjC,qBAAqB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC/C,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IAEX,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC;CACvE;AAED,MAAM,WAAW,SAAS;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,eAAe,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAE/B,UAAU,IAAI,MAAM,CAAC;IACrB,kBAAkB,IAAI,YAAY,CAAC;IACnC,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACjD,gBAAgB,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7D,aAAa,IAAI,IAAI,CAAC;IAEtB,MAAM,IAAI,OAAO,CAAC;IAClB,QAAQ,IAAI,eAAe,CAAC;IAC5B,MAAM,IAAI,MAAM,CAAC;IACjB,IAAI,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACtC,SAAS,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC3C;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,mBAAmB,CAAC,CAAC,CAAC;IACpE,WAAW,EAAE,YAAY,CAAC;IAE1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,CAAC,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,CAAC,CAAC;IAC1C,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;IAClB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC;IACxB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACrC,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3E,MAAM,IAAI,OAAO,CAAC;IAClB,QAAQ,IAAI,eAAe,CAAC;IAC5B,MAAM,IAAI,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAiB,SAAQ,mBAAmB,CAAC,gBAAgB,CAAC;IAC9E,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,gBAAgB,CAAC;CACnD;AAED,MAAM,WAAW,YAAa,SAAQ,mBAAmB,CAAC,YAAY,CAAC;IACtE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAAC;CACjC;AAED,MAAM,WAAW,6BAA8B,SAAQ,mBAAmB,CAAC,6BAA6B,CAAC;IACxG,kBAAkB,CAAC,kBAAkB,EAAE,MAAM,GAAG,6BAA6B,CAAC;IAC9E,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,6BAA6B,CAAC;CAChE;AAED,MAAM,WAAW,4BAA6B,SAAQ,mBAAmB,CAAC,4BAA4B,CAAC;IACtG,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,4BAA4B,CAAC;CACzD;AAED,MAAM,WAAW,eAAgB,SAAQ,mBAAmB,CAAC,eAAe,CAAC;IAC5E,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAAC;CAC1C;AAED,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB,CAAC,oBAAoB,CAAC;IACtF,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,oBAAoB,CAAC;CACvE;AAED,MAAM,WAAW,wBAAyB,SAAQ,mBAAmB,CAAC,wBAAwB,CAAC;CAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"TransactionUtils.d.ts","sourceRoot":"","sources":["../../src/utils/TransactionUtils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1C,qBAAa,gBAAgB;WACd,QAAQ,CAAC,WAAW,EAAE,eAAe,EAAE,aAAa,UAAQ,GAAG,MAAM;WA4BrE,MAAM,CAAC,WAAW,EAAE,eAAe,EAAE,aAAa,UAAQ,GAAG,MAAM;CAKjF"}
1
+ {"version":3,"file":"TransactionUtils.d.ts","sourceRoot":"","sources":["../../src/utils/TransactionUtils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1C,qBAAa,gBAAgB;WACd,QAAQ,CAAC,WAAW,EAAE,eAAe,EAAE,aAAa,UAAQ,GAAG,MAAM;WAgCrE,MAAM,CAAC,WAAW,EAAE,eAAe,EAAE,aAAa,UAAQ,GAAG,MAAM;CAKjF"}
@@ -20,6 +20,9 @@ export class TransactionUtils {
20
20
  fields.push(toBeArray(transaction["v"] - Constants.ETHEREUM_RECOVERY_ID_OFFSET));
21
21
  fields.push("0x" + transaction["r"]);
22
22
  fields.push("0x" + transaction["s"]);
23
+ if (transaction.legacySecondSignature) {
24
+ fields.push(`0x${transaction.legacySecondSignature}`);
25
+ }
23
26
  }
24
27
  const encoded = encodeRlp(fields);
25
28
  const payload = Constants.EIP_1559_PREFIX + encoded.substring(2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkecosystem/typescript-crypto",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "engines": {
5
5
  "node": ">=20.12.2"
6
6
  },
@@ -37,7 +37,6 @@ export class PrivateKey {
37
37
 
38
38
  async sign(message: string): Promise<RecoverableSignature> {
39
39
  const hash = keccak256("0x" + message).slice(2);
40
-
41
40
  const signature = await signAsync(hash, this.privateKey);
42
41
 
43
42
  return {
@@ -46,4 +45,13 @@ export class PrivateKey {
46
45
  v: signature.recovery + Constants.ETHEREUM_RECOVERY_ID_OFFSET,
47
46
  };
48
47
  }
48
+
49
+ async signToEcdsa(message: string): Promise<string> {
50
+ const hash = keccak256("0x" + message).slice(2);
51
+ const signature = await signAsync(hash, this.privateKey);
52
+
53
+ const v = signature.recovery + Constants.ETHEREUM_RECOVERY_ID_OFFSET;
54
+ // @see https://github.com/ArkEcosystem/mainsail/blob/16e50d45dcfbf15b20245f11b123634f0fd0b713/packages/utils/source/format-ecdsa-signature.ts#L2
55
+ return signature.toCompactHex() + v.toString(16).padStart(2, "0");
56
+ }
49
57
  }
@@ -70,6 +70,14 @@ export abstract class AbstractTransactionBuilder<T extends ITransactionBuilder<T
70
70
  return this as unknown as T;
71
71
  }
72
72
 
73
+ public async legacySecondSign(passphrase: string, secondPassprase: string): Promise<T> {
74
+ await this.sign(passphrase);
75
+
76
+ this.transaction = await this.transaction.legacySecondSign(PrivateKey.fromPassphrase(secondPassprase));
77
+
78
+ return this as unknown as T;
79
+ }
80
+
73
81
  public verify(): boolean {
74
82
  return this.transaction.verify();
75
83
  }
@@ -38,6 +38,14 @@ export abstract class AbstractTransaction implements ITransaction {
38
38
  return this;
39
39
  }
40
40
 
41
+ public async legacySecondSign(privateKey: PrivateKey): Promise<ITransaction> {
42
+ const hash = TransactionUtils.toBuffer(this.data, true).toString("hex");
43
+
44
+ this.data.legacySecondSignature = await privateKey.signToEcdsa(hash);
45
+
46
+ return this;
47
+ }
48
+
41
49
  public recoverSender(): void {
42
50
  const publicKey = this.recoverPublicKey();
43
51
 
@@ -64,6 +72,7 @@ export abstract class AbstractTransaction implements ITransaction {
64
72
  "gas",
65
73
  "nonce",
66
74
  "senderPublicKey",
75
+ "legacySecondSignature",
67
76
  "to",
68
77
  "value",
69
78
  "data",
package/src/types.ts CHANGED
@@ -4,6 +4,7 @@ import { Result } from "ethers";
4
4
  export interface TransactionData {
5
5
  gasPrice?: string | null;
6
6
  network?: number | string | null;
7
+ legacySecondSignature?: number | string | null;
7
8
  hash?: string | null;
8
9
  gas?: string | null;
9
10
  nonce?: number | string | null;
@@ -36,6 +37,7 @@ export interface ITransaction {
36
37
  getPayload(): string;
37
38
  refreshPayloadData(): ITransaction;
38
39
  sign(privateKey: unknown): Promise<ITransaction>;
40
+ legacySecondSign(privateKey: unknown): Promise<ITransaction>;
39
41
  recoverSender(): void;
40
42
 
41
43
  verify(): boolean;
@@ -54,6 +56,7 @@ export interface ITransactionBuilder<T extends ITransactionBuilder<T>> {
54
56
  nonce(nonce: string): T;
55
57
  network(network: number): T;
56
58
  sign(passphrase: string): Promise<T>;
59
+ legacySecondSign(passphrase: string, secondPassphrase: string): Promise<T>;
57
60
  verify(): boolean;
58
61
  toObject(): TransactionData;
59
62
  toJson(): string;
@@ -22,6 +22,10 @@ export class TransactionUtils {
22
22
  fields.push(toBeArray(transaction["v"] - Constants.ETHEREUM_RECOVERY_ID_OFFSET));
23
23
  fields.push("0x" + transaction["r"]);
24
24
  fields.push("0x" + transaction["s"]);
25
+
26
+ if (transaction.legacySecondSignature) {
27
+ fields.push(`0x${transaction.legacySecondSignature}`);
28
+ }
25
29
  }
26
30
 
27
31
  const encoded = encodeRlp(fields);
@@ -0,0 +1,19 @@
1
+ {
2
+ "data": {
3
+ "network": 10000,
4
+ "nonce": "1",
5
+ "gasPrice": "5000000000",
6
+ "gas": "21000",
7
+ "to": "0x6F0182a0cc707b055322CcF6d4CB6a5Aff1aEb22",
8
+ "value": "100000000",
9
+ "data": "",
10
+ "v": 28,
11
+ "r": "104665257d4dea61c4654e74c6c0f6cd0a398905781c3040bea67dc641a66da0",
12
+ "s": "46d718d04b2331f3b0561808549ed3f3f0d867a284acf6b334869078df7a9136",
13
+ "senderPublicKey": "0243333347c8cbf4e3cbc7a96964181d02a2b0c854faa2fef86b4b8d92afcf473d",
14
+ "from": "0x1E6747BEAa5B4076a6A98D735DF8c35a70D18Bdd",
15
+ "hash": "b7927d90b38cd1296351f26145b3d8b0674fdc9b8721bc1a10f71a12bcbccf60",
16
+ "legacySecondSignature": "104665257d4dea61c4654e74c6c0f6cd0a398905781c3040bea67dc641a66da046d718d04b2331f3b0561808549ed3f3f0d867a284acf6b334869078df7a91361c"
17
+ },
18
+ "serialized": "02f8b0822710018085012a05f200825208946f0182a0cc707b055322ccf6d4cb6a5aff1aeb228405f5e10080c001a0104665257d4dea61c4654e74c6c0f6cd0a398905781c3040bea67dc641a66da0a046d718d04b2331f3b0561808549ed3f3f0d867a284acf6b334869078df7a9136b841104665257d4dea61c4654e74c6c0f6cd0a398905781c3040bea67dc641a66da046d718d04b2331f3b0561808549ed3f3f0d867a284acf6b334869078df7a91361c"
19
+ }
@@ -1,4 +1,5 @@
1
1
  import fixture from "@tests/fixtures/transactions/transfer.json";
2
+ import legacySecondSignatureFixture from "@tests/fixtures/transactions/transfer-legacy-second-signature.json";
2
3
  import fixtureTransferLargeAmount from "@tests/fixtures/transactions/transfer-large-amount.json";
3
4
  import identityFixture from "@tests/fixtures/identity.json";
4
5
 
@@ -50,6 +51,35 @@ it("should sign a transaction", async () => {
50
51
  expect(transaction.verify()).toBe(true);
51
52
  });
52
53
 
54
+ it("should build a transaction using legacy second signature", async () => {
55
+ const transaction = (
56
+ await TransferBuilder.new()
57
+ .value(legacySecondSignatureFixture.data.value)
58
+ .to(legacySecondSignatureFixture.data.to)
59
+ .nonce(legacySecondSignatureFixture.data.nonce)
60
+ .gasPrice(legacySecondSignatureFixture.data.gasPrice)
61
+ .gas(legacySecondSignatureFixture.data.gas)
62
+ .network(legacySecondSignatureFixture.data.network)
63
+ .legacySecondSign(identityFixture.passphrase, identityFixture.passphrase)
64
+ ).transaction;
65
+
66
+ expect(transaction.data.gasPrice).toBe(legacySecondSignatureFixture.data.gasPrice);
67
+ expect(transaction.data.nonce).toBe(legacySecondSignatureFixture.data.nonce);
68
+ expect(transaction.data.network).toBe(legacySecondSignatureFixture.data.network);
69
+ expect(transaction.data.gas).toBe(legacySecondSignatureFixture.data.gas);
70
+ expect(transaction.data.to).toBe(legacySecondSignatureFixture.data.to);
71
+ expect(transaction.data.value).toBe(legacySecondSignatureFixture.data.value);
72
+ expect(transaction.data.v).toBe(legacySecondSignatureFixture.data.v);
73
+ expect(transaction.data.r).toBe(legacySecondSignatureFixture.data.r);
74
+ expect(transaction.data.s).toBe(legacySecondSignatureFixture.data.s);
75
+ expect(transaction.data.hash).toBe(legacySecondSignatureFixture.data.hash);
76
+ expect(transaction.data.hash).toBe(legacySecondSignatureFixture.data.hash);
77
+ expect(transaction.data.legacySecondSignature).toBe(legacySecondSignatureFixture.data.legacySecondSignature);
78
+
79
+ expect(transaction.serialize().toString("hex")).toEqual(legacySecondSignatureFixture.serialized);
80
+ expect(transaction.verify()).toBe(true);
81
+ });
82
+
53
83
  it("should handle large amounts", async () => {
54
84
  const transaction = (
55
85
  await TransferBuilder.new()