Skip to content

Commit

Permalink
Style/smart contract file (#590)
Browse files Browse the repository at this point in the history
* fix lint smart contract file

* argsKey and coinsKey for populate datastore

* Move datastore with Smartcontract generation file
  • Loading branch information
Ben-Rey committed May 3, 2024
1 parent a143db3 commit 865fcde
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 161 deletions.
1 change: 0 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

80 changes: 80 additions & 0 deletions packages/massa-web3/deployer_generation/dataStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { u64ToBytes, u8toByte } from '@massalabs/web3-utils'
import { ONE, ZERO, ZERO_BYTE } from '../src/experimental/utils'
import { Args } from '../src/experimental/basicElements/args'

const CONTRACTS_NUMBER_KEY = new Uint8Array([ZERO_BYTE])

type DatastoreContract = {
data: Uint8Array
args: Uint8Array
coins: bigint
}

/**
* Generates a key for coin data in the datastore.
*
* @param offset - The offset to use when generating the key.
* @returns A Uint8Array representing the key.
*/
function coinsKey(offset: number): Uint8Array {
return new Args()
.addU64(BigInt(offset + ONE))
.addUint8Array(u8toByte(ONE))
.serialize()
}

/**
* Generates a key for args data in the datastore.
*
* @param offset - The offset to use when generating the key.
* @returns A Uint8Array representing the key.
*/
function argsKey(offset: number): Uint8Array {
return new Args()
.addU64(BigInt(offset + ONE))
.addUint8Array(u8toByte(ZERO))
.serialize()
}

/**
* Generates a key for contract data in the datastore.
*
* @param offset - The offset to use when generating the key.
* @returns A Uint8Array representing the key.
*/
function contractKey(offset: number): Uint8Array {
return u64ToBytes(BigInt(offset + ONE))
}

/**
* Populates the datastore with the contracts.
*
* @remarks
* This function is to be used in conjunction with the deployer smart contract.
* The deployer smart contract expects to have an execution datastore in a specific state.
* This function populates the datastore according to that expectation.
*
* @param contracts - The contracts to populate the datastore with.
*
* @returns The populated datastore.
*/
export function populateDatastore(
contracts: DatastoreContract[]
): Map<Uint8Array, Uint8Array> {
const datastore = new Map<Uint8Array, Uint8Array>()

// set the number of contracts in the first key of the datastore
datastore.set(CONTRACTS_NUMBER_KEY, u64ToBytes(BigInt(contracts.length)))

contracts.forEach((contract, i) => {
datastore.set(contractKey(i), contract.data)
if (contract.args) {
datastore.set(argsKey(i), contract.args)
}
if (contract.coins > ZERO) {
datastore.set(coinsKey(i), u64ToBytes(contract.coins))
}
})

return datastore
}
69 changes: 69 additions & 0 deletions packages/massa-web3/src/experimental/basicElements/bytecode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* A module to compile and execute byte code.
*
* @remarks
* The difference between byte code and a smart contract is that the byte code is the raw code that will be
* executed on the blockchain, while a smart contract is the code that is already deployed on the blockchain.
* The byte code is only ephemeral and will be executed only once.
* A smart contract has an address and exposes functions that can be called multiple times.
*
*/
import { BlockchainClient } from '../client'
import { ZERO } from '../utils'
import { PrivateKey } from './keys'
import { Operation } from './operation'
import {
OperationManager,
ExecuteOperation,
calculateExpirePeriod,
OperationType,
} from './operationManager'

export const MAX_GAS_EXECUTE = 3980167295n

type ExecuteOption = {
fee?: bigint
periodToLive?: number
maxCoins?: bigint
maxGas?: bigint
datastore?: Map<Uint8Array, Uint8Array>
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
function compile(_source: string): Promise<Uint8Array> {
throw new Error('Not implemented')
}

/**
*
* Executes a byte code on the blockchain.
*
* @param client - The client to connect to the desired blockchain.
* @param privateKey - The private key of the account that will execute the byte code.
* @param byteCode - The byte code to execute.
* @param opts - Optional execution details.
*
* @returns The operation.
*/
export async function execute(
client: BlockchainClient,
privateKey: PrivateKey,
byteCode: Uint8Array,
opts: ExecuteOption
): Promise<Operation> {
const operation = new OperationManager(privateKey, client)
const details: ExecuteOperation = {
fee: opts?.fee ?? (await client.getMinimalFee()),
expirePeriod: calculateExpirePeriod(
await client.fetchPeriod(),
opts?.periodToLive
),
type: OperationType.ExecuteSmartContractBytecode,
maxCoins: opts?.maxCoins ?? BigInt(ZERO),
maxGas: opts?.maxGas || MAX_GAS_EXECUTE,
contractDataBinary: byteCode,
datastore: opts.datastore,
}

return new Operation(client, await operation.send(details))
}
Loading

0 comments on commit 865fcde

Please sign in to comment.