Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add entrypoints #514

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
80698cc
Add controllers si facades
danielailie Oct 17, 2024
97bf2d1
Export facades and controllers
danielailie Oct 21, 2024
6a55710
Clean up and add tests
danielailie Oct 23, 2024
af35e6a
Merge branch 'main' into TOOL-276-implement-facade
danielailie Oct 23, 2024
d4fbf59
Merge branch 'feat/unify' into TOOL-276-implement-facade
danielailie Oct 23, 2024
c5df031
Clean up relay v3
danielailie Oct 23, 2024
0be9170
Update function name
danielailie Oct 23, 2024
8792820
Refactor controller methods input
danielailie Oct 24, 2024
ab8ec97
Fix tests
danielailie Oct 24, 2024
497efad
refactor input parameters
danielailie Oct 30, 2024
07cf5eb
Add missing methods
danielailie Nov 4, 2024
f2b8631
Add delegation folder
danielailie Nov 12, 2024
6a0a4ea
Add account management folder
danielailie Nov 12, 2024
de2fb06
Add token management folder
danielailie Nov 12, 2024
0c4004b
Add relayed and accounts folders
danielailie Nov 13, 2024
1f3b7d6
Move smartContracts folder to abi folder
danielailie Nov 13, 2024
a019513
Add smart contract folder
danielailie Nov 13, 2024
3860d59
Add transfers folder
danielailie Nov 13, 2024
a973694
Update account parameters
danielailie Nov 13, 2024
29f017f
Update input parameters for delegation
danielailie Nov 13, 2024
489f88a
Update smart contract controller
danielailie Nov 13, 2024
bc0beab
Update Token management inputs
danielailie Nov 13, 2024
6bc9456
Update transfers input
danielailie Nov 13, 2024
bb29def
Merge branch 'feat/next' into TOOL-276-implement-facade
danielailie Nov 13, 2024
f1c9b9c
Fix tests
danielailie Nov 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 50 additions & 2 deletions src/account.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { Address } from "./address";
import { LibraryConfig } from "./config";
import { IAccount } from "./controllers/interfaces";
import { IAccountBalance, IAddress, INonce } from "./interface";
import { UserSigner, UserWallet } from "./wallet";

/**
* An abstraction representing an account (user or Smart Contract) on the Network.
*/
export class Account {
export class Account implements IAccount {
/**
* The address of the account.
*/
Expand All @@ -15,18 +18,30 @@ export class Account {
*/
nonce: INonce = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, we are using bigint for nonce. Would it be a breaking change if we'd do that here?


/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good that we now have these deprecation markers.

* @deprecated This will be remove with the next release as not needed anymore.
*/
/**
* The balance of the account.
*/
balance: IAccountBalance = "0";

/**
* The signer of the account.
*/
signer?: UserSigner;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible, let's switch to private access modifier (so that we hide the current workaround of having a "frankenstein" Account).


/**
* Creates an account object from an address
*/
constructor(address: IAddress) {
constructor(address: IAddress, signer?: UserSigner) {
this.address = address;
this.signer = signer;
}

/**
* @deprecated This will be remove with the next release as not needed anymore.
*/
/**
* Updates account properties (such as nonce, balance).
*/
Expand Down Expand Up @@ -61,4 +76,37 @@ export class Account {
balance: this.balance.toString(),
};
}

sign(data: Uint8Array): Promise<Uint8Array> {
if (!this.signer) {
throw new Error("Signer not initialiezed, please provide the signer when account is instantiated");
}
return this.signer.sign(data);
}

static fromPem(path: string, hrp: string = LibraryConfig.DefaultAddressHrp): Account {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the specs, the static methods are prefixed with new...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new_from_mnemonic is also missing.

const userSigner = UserSigner.fromPem(path);
return new Account(userSigner.getAddress(hrp), userSigner);
}

static fromWallet(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below (and in PY & specs), we use the term keystore. Perhaps this can also be named fromKeystoreObject (parameters can also be renamed)?

keyFileObject: any,
password: string,
addressIndex?: number,
hrp: string = LibraryConfig.DefaultAddressHrp,
): Account {
const userSigner = UserSigner.fromWallet(keyFileObject, password, addressIndex);
return new Account(userSigner.getAddress(hrp), userSigner);
}

static fromKeystore(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe should we use the options parameters "pattern" in this class, as well?

filePath: string,
password: string,
addressIndex?: number,
hrp: string = LibraryConfig.DefaultAddressHrp,
): Account {
const secretKey = UserWallet.loadSecretKey(filePath, password, addressIndex);
const userSigner = new UserSigner(secretKey);
return new Account(userSigner.getAddress(hrp), userSigner);
}
}
12 changes: 4 additions & 8 deletions src/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
import { LibraryConfig } from "./config";
import { CURRENT_NUMBER_OF_SHARDS_WITHOUT_META, METACHAIN_ID, WasmVirtualMachine } from "./constants";
import * as errors from "./errors";
import { IAddress } from "./interface";
import { bigIntToBuffer } from "./tokenOperations/codec";
const createKeccakHash = require("keccak");

Check warning on line 8 in src/address.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

Require statement not part of import statement

/**
* The length (in bytes) of a public key (from which a bech32 address can be obtained).
Expand All @@ -13,15 +14,10 @@

const SMART_CONTRACT_HEX_PUBKEY_PREFIX = "0".repeat(16);

interface IAddress {
getPublicKey(): Buffer;
getHrp(): string;
}

/**
* An Address, as an immutable object.
*/
export class Address {
export class Address implements IAddress {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll drop IAddress in v14, hopefully (if possible).

private readonly publicKey: Buffer;
private readonly hrp: string;

Expand Down Expand Up @@ -298,7 +294,7 @@

computeContractAddress(deployer: IAddress, deploymentNonce: bigint): Address {
const initialPadding = Buffer.alloc(8, 0);
const ownerPubkey = deployer.getPublicKey();
const ownerPubkey = deployer.pubkey();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getPublicKey() is the method listed in the specs (here, below).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IAddress has only pubkey, we discussed that we will drop that one so.. no need to add extra implementation

const shardSelector = ownerPubkey.slice(30);
const ownerNonceBytes = Buffer.alloc(8);

Expand All @@ -315,7 +311,7 @@
}

getShardOfAddress(address: IAddress): number {
return this.getShardOfPubkey(address.getPublicKey(), this.numberOfShardsWithoutMeta);
return this.getShardOfPubkey(address.pubkey(), this.numberOfShardsWithoutMeta);
}

private getShardOfPubkey(pubkey: Uint8Array, numberOfShards: number): number {
Expand Down
64 changes: 64 additions & 0 deletions src/controllers/accountController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { IAddress } from "../interface";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the methods pubkey() and bech32() are deprecated in the Address class, I think we can create locally a new interface that has toBech32() and getPublicKey(), given the fact that everybody will use that class.

import { Transaction } from "../transaction";
import { TransactionComputer } from "../transactionComputer";
import { AccountTransactionsFactory, TransactionsFactoryConfig } from "../transactionsFactories";
import { IAccount } from "./interfaces";

export class AccountController {
private factory: AccountTransactionsFactory;
private txComputer: TransactionComputer;

constructor(chainId: string) {
this.factory = new AccountTransactionsFactory({ config: new TransactionsFactoryConfig({ chainID: chainId }) });
this.txComputer = new TransactionComputer();
}

async createTransactionForSavingKeyValue(sender: IAccount, options: SaveKeyValueInput): Promise<Transaction> {
const transaction = this.factory.createTransactionForSavingKeyValue({
sender: sender.address,
keyValuePairs: options.keyValuePairs,
});

transaction.nonce = options.nonce;
transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction));

return transaction;
}

async createTransactionForSettingGuardian(sender: IAccount, options: SetGuardianInput): Promise<Transaction> {
const transaction = this.factory.createTransactionForSettingGuardian({ ...options, sender: sender.address });

transaction.nonce = options.nonce;
transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction));

return transaction;
}

async createTransactionForGuardingAccount(
sender: IAccount,
options: GuardianInteractionInput,
): Promise<Transaction> {
const transaction = this.factory.createTransactionForGuardingAccount({ sender: sender.address });

transaction.nonce = options.nonce;
transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction));

return transaction;
}

async createTransactionForUnguardingAccount(
sender: IAccount,
options: GuardianInteractionInput,
): Promise<Transaction> {
const transaction = this.factory.createTransactionForUnguardingAccount({ sender: sender.address });

transaction.nonce = options.nonce;
transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction));

return transaction;
}
}

type SetGuardianInput = { nonce: bigint; guardianAddress: IAddress; serviceID: string };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice 🎉

type SaveKeyValueInput = { nonce: bigint; keyValuePairs: Map<Uint8Array, Uint8Array> };
type GuardianInteractionInput = { nonce: bigint };
Loading
Loading