From 41b8fa2cebc2bdbcac910496bb319111ef67bca5 Mon Sep 17 00:00:00 2001 From: Kai Hirota <34954529+kaihirota@users.noreply.github.com> Date: Tue, 27 Feb 2024 17:31:17 +1100 Subject: [PATCH 1/7] add registration workflow --- src/ImmutableX.ts | 12 +++++++ src/types/signers.ts | 11 +++++++ src/utils/stark/starkSigner.ts | 26 +++++++++++++++ src/workflows/registration.ts | 58 ++++++++++++++++++++++++++++++++-- src/workflows/workflows.ts | 7 ++++ 5 files changed, 111 insertions(+), 3 deletions(-) diff --git a/src/ImmutableX.ts b/src/ImmutableX.ts index 1dbcf4d2..d97ebece 100644 --- a/src/ImmutableX.ts +++ b/src/ImmutableX.ts @@ -169,6 +169,18 @@ export class ImmutableX { }); } + /** + * Register a User to StarkEx contract if they are not already + * @param walletConnection - the pair of L1/L2 signers + * @returns a promise that resolves with void if successful + * @throws {@link index.IMXError} + */ + public registerOnchain(walletConnection: WalletConnection) { + return this.workflows.registerOnchain(walletConnection).catch(err => { + throw formatError(err); + }); + } + /** * Checks if a User is registered on on-chain * @param walletConnection - the pair of L1/L2 signers diff --git a/src/types/signers.ts b/src/types/signers.ts index 706364a3..44ccccdd 100644 --- a/src/types/signers.ts +++ b/src/types/signers.ts @@ -1,4 +1,5 @@ import { Signer as EthSigner } from '@ethersproject/abstract-signer'; +import { ec } from 'elliptic'; export { EthSigner }; @@ -13,6 +14,16 @@ export interface StarkSigner { * @returns the signed prefixed-message */ signMessage(message: string): Promise; + + /** + * Signs the prefixed-message + * @params message - this must be a UTF8-message + * @returns the signed prefixed-message + */ + sign(message: string): Promise; + + getYCoordinate(): string; + /** * Get the Signer address * @returns the Signer's checksum address diff --git a/src/utils/stark/starkSigner.ts b/src/utils/stark/starkSigner.ts index 79f5afef..68fde42b 100644 --- a/src/utils/stark/starkSigner.ts +++ b/src/utils/stark/starkSigner.ts @@ -28,6 +28,17 @@ export class StandardStarkSigner implements StarkSigner { ); } + public async sign(msg: string): Promise { + return this.keyPair.sign(this.fixMsgHashLen(msg)); + } + + public getYCoordinate(): string { + return encUtils.sanitizeBytes( + this.keyPair.getPublic().getY().toString(16), + 2, + ); + } + /* The function _truncateToN in lib/elliptic/ec/index.js does a shift-right of delta bits, if delta is positive, where @@ -60,3 +71,18 @@ export class StandardStarkSigner implements StarkSigner { export function createStarkSigner(starkPrivateKey: string): StarkSigner { return new StandardStarkSigner(starkPrivateKey); } + +export function serializePackedSignature( + sig: ec.Signature, + pubY: string, +): string { + return encUtils.sanitizeHex( + encUtils.padLeft(sig.r.toString(16), 64) + + encUtils.padLeft(sig.s.toString(16), 64, '0') + + encUtils.padLeft( + new BN(encUtils.removeHexPrefix(pubY), 'hex').toString(16), + 64, + '0', + ), + ); +} diff --git a/src/workflows/registration.ts b/src/workflows/registration.ts index 30dc41a8..b8c1194d 100644 --- a/src/workflows/registration.ts +++ b/src/workflows/registration.ts @@ -1,11 +1,17 @@ +import { ImmutableXConfiguration } from '..'; import { UsersApi, GetSignableRegistrationResponse, RegisterUserResponse, } from '../api'; -import { WalletConnection } from '../types'; -import { signRaw } from '../utils'; -import { Registration } from '../contracts'; +import { StarkSigner, WalletConnection } from '../types'; +import { serializePackedSignature, signRaw, starkEcOrder } from '../utils'; +import { Registration, CoreV4__factory } from '../contracts'; +import { solidityKeccak256 } from 'ethers/lib/utils'; +import BN from 'bn.js'; +import * as encUtils from 'enc-utils'; +import { ec } from 'elliptic'; +import { TransactionResponse } from '@ethersproject/providers'; type registerOffchainWorkflowParams = WalletConnection & { usersApi: UsersApi; @@ -81,3 +87,49 @@ export async function getSignableRegistrationOnchain( verification_signature: response.data.verification_signature, }; } + +export async function signRegisterEthAddress( + starkSigner: StarkSigner, + ethAddress: string, + starkPublicKey: string, +): Promise { + const hash: string = solidityKeccak256( + ['string', 'address', 'uint256'], + ['UserRegistration:', ethAddress, starkPublicKey], + ); + const msgHash: BN = new BN(encUtils.removeHexPrefix(hash), 16); + const modMsgHash: BN = msgHash.mod(starkEcOrder); + const signature: ec.Signature = await starkSigner.sign( + modMsgHash.toString(16), + ); + const pubY: string = encUtils.sanitizeHex(starkSigner.getYCoordinate()); + return serializePackedSignature(signature, pubY); +} + +export async function registerOnchainWorkflow( + walletConnection: WalletConnection, + config: ImmutableXConfiguration, +): Promise { + const ethAddress = await walletConnection.ethSigner.getAddress(); + const starkPublicKey = await walletConnection.starkSigner.getAddress(); + + const signature = await signRegisterEthAddress( + walletConnection.starkSigner, + ethAddress, + starkPublicKey, + ); + + const contract = CoreV4__factory.connect( + config.ethConfiguration.coreContractAddress, + walletConnection.ethSigner, + ); + + const populatedTransaction = + await contract.populateTransaction.registerEthAddress( + ethAddress, + starkPublicKey, + signature, + ); + + return walletConnection.ethSigner.sendTransaction(populatedTransaction); +} diff --git a/src/workflows/workflows.ts b/src/workflows/workflows.ts index 098ef1c1..15eda3c4 100644 --- a/src/workflows/workflows.ts +++ b/src/workflows/workflows.ts @@ -42,6 +42,7 @@ import { Registration__factory } from '../contracts'; import { isRegisteredOnChainWorkflow, registerOffchainWorkflow, + registerOnchainWorkflow, } from './registration'; import { mintingWorkflow } from './minting'; import { transfersWorkflow, batchTransfersWorkflow } from './transfers'; @@ -126,6 +127,12 @@ export class Workflows { ); } + public async registerOnchain(walletConnection: WalletConnection) { + await this.validateChain(walletConnection.ethSigner); + + return registerOnchainWorkflow(walletConnection, this.config); + } + public async registerOffchain(walletConnection: WalletConnection) { await this.validateChain(walletConnection.ethSigner); From 415bbabba8c7b5838c6ee131a9eb832d53786f94 Mon Sep 17 00:00:00 2001 From: Kai Hirota <34954529+kaihirota@users.noreply.github.com> Date: Tue, 27 Feb 2024 17:33:42 +1100 Subject: [PATCH 2/7] bump version --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 365d71c6..ddabbd23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.4.0] - 2024-02-27 + +### Added + +- Added on chain registration workflow for StarkEx V4 contract. + ## [3.3.0] - 2024-02-27 ### Added diff --git a/package.json b/package.json index 910c64e2..9f1c0cb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@imtbl/core-sdk", - "version": "3.3.0", + "version": "3.4.0", "description": "Immutable Core SDK", "main": "dist/index.cjs.js", "module": "dist/index.es.js", From feff43d3f77e98e7e02fcdaa9031065cb42d6e00 Mon Sep 17 00:00:00 2001 From: Kai Hirota <34954529+kaihirota@users.noreply.github.com> Date: Tue, 27 Feb 2024 17:50:35 +1100 Subject: [PATCH 3/7] bump version and add changelog --- CHANGELOG.md | 3 ++- package.json | 2 +- src/types/signers.ts | 14 +++++++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ddabbd23..516cc5c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [3.4.0] - 2024-02-27 +## [4.0.0] - 2024-02-27 ### Added - Added on chain registration workflow for StarkEx V4 contract. +- [BREAKING CHANGE] Update `StarkSigner` interface to add 2 methods - `signMessage` and `getYCoordinate`. ## [3.3.0] - 2024-02-27 diff --git a/package.json b/package.json index 9f1c0cb3..ff31e184 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@imtbl/core-sdk", - "version": "3.4.0", + "version": "4.0.0", "description": "Immutable Core SDK", "main": "dist/index.cjs.js", "module": "dist/index.es.js", diff --git a/src/types/signers.ts b/src/types/signers.ts index 44ccccdd..eb2ce598 100644 --- a/src/types/signers.ts +++ b/src/types/signers.ts @@ -15,6 +15,12 @@ export interface StarkSigner { */ signMessage(message: string): Promise; + /** + * Get the Signer address + * @returns the Signer's checksum address + */ + getAddress(): string | Promise; + /** * Signs the prefixed-message * @params message - this must be a UTF8-message @@ -22,13 +28,11 @@ export interface StarkSigner { */ sign(message: string): Promise; - getYCoordinate(): string; - /** - * Get the Signer address - * @returns the Signer's checksum address + * Get the Y-coordinate of the public key + * @returns the Y-coordinate of the public key */ - getAddress(): string | Promise; + getYCoordinate(): string; } /** From e440c6e15d4dc5c81d172bafd446c930cc132889 Mon Sep 17 00:00:00 2001 From: Kai Hirota <34954529+kaihirota@users.noreply.github.com> Date: Tue, 27 Feb 2024 17:51:16 +1100 Subject: [PATCH 4/7] remove breaking change --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 516cc5c3..8b4fe537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added on chain registration workflow for StarkEx V4 contract. -- [BREAKING CHANGE] Update `StarkSigner` interface to add 2 methods - `signMessage` and `getYCoordinate`. +- Update `StarkSigner` interface to add 2 methods - `signMessage` and `getYCoordinate`. ## [3.3.0] - 2024-02-27 From 131773050abe1ebcd8a8e0254de140b97bdc6223 Mon Sep 17 00:00:00 2001 From: Bryan Dichtl Date: Wed, 28 Feb 2024 09:37:54 +1100 Subject: [PATCH 5/7] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ff31e184..9f1c0cb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@imtbl/core-sdk", - "version": "4.0.0", + "version": "3.4.0", "description": "Immutable Core SDK", "main": "dist/index.cjs.js", "module": "dist/index.es.js", From 8c0a16e205ebfd64b1ef2caa9f19e62900dbc938 Mon Sep 17 00:00:00 2001 From: Bryan Dichtl Date: Wed, 28 Feb 2024 09:37:59 +1100 Subject: [PATCH 6/7] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b4fe537..7c0caa5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [4.0.0] - 2024-02-27 +## [3.4.0] - 2024-02-27 ### Added From b4e0984546dcb9775a28ce1c792898af3c34755e Mon Sep 17 00:00:00 2001 From: Kai Hirota <34954529+kaihirota@users.noreply.github.com> Date: Wed, 28 Feb 2024 09:41:23 +1100 Subject: [PATCH 7/7] Update src/ImmutableX.ts --- src/ImmutableX.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImmutableX.ts b/src/ImmutableX.ts index d97ebece..57239664 100644 --- a/src/ImmutableX.ts +++ b/src/ImmutableX.ts @@ -170,7 +170,7 @@ export class ImmutableX { } /** - * Register a User to StarkEx contract if they are not already + * Register a User to StarkEx contract if they are not registered already * @param walletConnection - the pair of L1/L2 signers * @returns a promise that resolves with void if successful * @throws {@link index.IMXError}