Skip to content
This repository has been archived by the owner on May 16, 2024. It is now read-only.

Commit

Permalink
add registration workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
kaihirota committed Feb 19, 2024
1 parent 9fb296c commit 6537754
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 3 deletions.
12 changes: 12 additions & 0 deletions src/ImmutableX.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions src/types/signers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Signer as EthSigner } from '@ethersproject/abstract-signer';
import { ec } from 'elliptic';

export { EthSigner };

Expand All @@ -13,6 +14,16 @@ export interface StarkSigner {
* @returns the signed prefixed-message
*/
signMessage(message: string): Promise<string>;

/**
* Signs the prefixed-message
* @params message - this must be a UTF8-message
* @returns the signed prefixed-message
*/
sign(message: string): Promise<ec.Signature>;

getYCoordinate(): string;

/**
* Get the Signer address
* @returns the Signer's checksum address
Expand Down
26 changes: 26 additions & 0 deletions src/utils/stark/starkSigner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ export class StandardStarkSigner implements StarkSigner {
);
}

public async sign(msg: string): Promise<ec.Signature> {
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
Expand Down Expand Up @@ -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',
),
);
}
58 changes: 55 additions & 3 deletions src/workflows/registration.ts
Original file line number Diff line number Diff line change
@@ -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, StarkV4__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;
Expand Down Expand Up @@ -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<string> {
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<TransactionResponse> {
const ethAddress = await walletConnection.ethSigner.getAddress();
const starkPublicKey = await walletConnection.starkSigner.getAddress();

const signature = await signRegisterEthAddress(
walletConnection.starkSigner,
ethAddress,
starkPublicKey,
);

const contract = StarkV4__factory.connect(
config.ethConfiguration.coreContractAddress,
walletConnection.ethSigner,
);

const populatedTransaction =
await contract.populateTransaction.registerEthAddress(
ethAddress,
starkPublicKey,
signature,
);

return walletConnection.ethSigner.sendTransaction(populatedTransaction);
}
7 changes: 7 additions & 0 deletions src/workflows/workflows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { Registration__factory } from '../contracts';
import {
isRegisteredOnChainWorkflow,
registerOffchainWorkflow,
registerOnchainWorkflow,
} from './registration';
import { mintingWorkflow } from './minting';
import { transfersWorkflow, batchTransfersWorkflow } from './transfers';
Expand Down Expand Up @@ -131,6 +132,12 @@ export class Workflows {
});
}

public async registerOnchain(walletConnection: WalletConnection) {
await this.validateChain(walletConnection.ethSigner);

return registerOnchainWorkflow(walletConnection, this.config);
}

public async isRegisteredOnchain(walletConnection: WalletConnection) {
await this.validateChain(walletConnection.ethSigner);

Expand Down

0 comments on commit 6537754

Please sign in to comment.