Skip to content

Commit

Permalink
Chains: Implement Collection Deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
imsk17 committed Feb 27, 2024
1 parent ae8efc9 commit c3e29e6
Show file tree
Hide file tree
Showing 13 changed files with 200 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/factory/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export namespace ChainFactoryConfigs {
"https://devnet-gateway.multiversx.com",
),
storage,
chainId: "D",
},
tonParams: {
bridgeAddress: "EQDI6P9gheuWLh1euThjFE2muUpa9tp2y49TD6Zz5oOF5gWL",
Expand Down
12 changes: 12 additions & 0 deletions src/handlers/evm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ export function evmHandler({
extraArgs,
);
},
async deployCollection(signer, da, ga) {
const contract = await new ERC721Royalty__factory(signer).deploy(
da.name,
da.symbol,
da.owner ?? signer,
{
...ga,
from: await signer.getAddress(),
},
);
return await contract.getAddress();
},
async mintNft(signer, ma) {
const minter = ERC721Royalty__factory.connect(ma.contract, signer);
return minter.mint(
Expand Down
13 changes: 12 additions & 1 deletion src/handlers/evm/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
Signer,
} from "ethers";
import { Bridge, BridgeStorage } from "../../contractsTypes/evm";
import { MintNft, TNftChain } from "../types";

import { DeployCollection, MintNft, TNftChain } from "../types";

export type TEvmHandler = TNftChain<
Signer,
Expand All @@ -25,6 +26,16 @@ export type TEvmHandler = TNftChain<
royaltyReceiver: string;
},
ContractTransactionResponse
> &
DeployCollection<
Signer,
{
name: string;
symbol: string;
owner?: string;
},
Overrides,
string
>;

export type TEvmParams = {
Expand Down
80 changes: 78 additions & 2 deletions src/handlers/multiversx/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ import {
BigUIntValue,
BytesType,
BytesValue,
ContractCallPayloadBuilder,
ContractFunction,
Field,
FieldDefinition,
ResultsParser,
SmartContract,
Struct,
StructType,
TokenTransfer,
Transaction,
TransactionPayload,
TransactionWatcher,
TypedValue,
VariadicValue,
} from "@multiversx/sdk-core/out";

Expand All @@ -31,6 +36,7 @@ export function multiversxHandler({
gatewayURL,
bridge,
storage,
chainId,
}: TMultiversXParams): TMultiversXHandler {
const abiRegistry = AbiRegistry.create(multiversXBridgeABI);
const multiversXBridgeContract = new SmartContract({
Expand Down Expand Up @@ -82,6 +88,44 @@ export function multiversxHandler({
royalty: BigInt(royalties),
};
},
async deployCollection(signer, da, ga) {
const builtInSC =
"erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u";
const args: TypedValue[] = [
BytesValue.fromUTF8(da.name),
BytesValue.fromUTF8(da.ticker),
];
const data = new ContractCallPayloadBuilder()
.setFunction(new ContractFunction("issueNonFungible"))
.setArgs(args)
.build();

const payment = TokenTransfer.egldFromAmount("0.05");

const tx = new Transaction({
data,
gasLimit: ga?.gasLimit ?? 60_000_000,
receiver: new Address(builtInSC.trim()),
sender: signer.getAddress(),
value: payment,
chainID: chainId,
});

const signed = await signer.sign(tx.serializeForSigning());

tx.applySignature(signed);

await provider.sendTransaction(tx);
const watcher = new TransactionWatcher(provider);
const transactionOnNetwork = await watcher.awaitCompleted(tx);

const result = transactionOnNetwork.contractResults.items.find(
(e: { data: string }) => e.data.startsWith("@"),
);
const tickerh: string =
result?.data.split("@")[2] ?? raise("failed to find ticker");
return Buffer.from(tickerh, "hex").toString("utf-8");
},
getProvider() {
return provider;
},
Expand All @@ -103,8 +147,40 @@ export function multiversxHandler({
getStorageContract() {
return storage;
},
async mintNft(_signer, _ma) {
throw new Error("unimplemented");
async mintNft(signer, ma) {
const args: TypedValue[] = [
BytesValue.fromUTF8(ma.ticker),
new BigUIntValue(1),
BytesValue.fromUTF8(ma.name),
new BigUIntValue(Number(ma.royalties) * 100 || 0),
BytesValue.fromUTF8(ma.hash || ""),
BytesValue.fromUTF8(ma.attrs || ""),
];
for (const uri of ma.uris) {
args.push(BytesValue.fromUTF8(uri));
}

const data = new ContractCallPayloadBuilder()
.setFunction(new ContractFunction("ESDTNFTCreate"))
.setArgs(args)
.build();

const tx = new Transaction({
data,
gasLimit:
3_000_000 +
data.length() * 1500 +
(ma.attrs?.length || 0 + (ma.hash?.length ?? 0) || 0) * 50000,
receiver: signer.getAddress(),
sender: signer.getAddress(),
value: 0,
chainID: chainId,
});

const signed = await signer.sign(tx.serializeForSigning());
tx.applySignature(signed);
const hash = await provider.sendTransaction(tx);
return hash;
},
transform(input) {
return {
Expand Down
12 changes: 10 additions & 2 deletions src/handlers/multiversx/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { INetworkProvider } from "@multiversx/sdk-network-providers/out/interface";
import { UserAddress } from "@multiversx/sdk-wallet/out/userAddress";
import { BridgeStorage } from "../../contractsTypes/evm";
import { MintNft, TSingularNftChain } from "../types";
import { DeployCollection, MintNft, TSingularNftChain } from "../types";

// Custom Interface because there is no such signer interface in mx-sdk.
export type TMultiversXSigner = {
Expand Down Expand Up @@ -38,6 +38,7 @@ export type NftIssueArgs = {
readonly royalties?: number;
readonly hash?: string;
readonly attrs?: string;
readonly ticker: string;
};

export type TMultiversXHandler = TSingularNftChain<
Expand All @@ -47,11 +48,18 @@ export type TMultiversXHandler = TSingularNftChain<
string,
INetworkProvider
> &
MintNft<TMultiversXSigner, NftIssueArgs, string>;
MintNft<TMultiversXSigner, NftIssueArgs, string> &
DeployCollection<
TMultiversXSigner,
{ name: string; ticker: string },
{ gasLimit: number },
string
>;

export type TMultiversXParams = {
provider: INetworkProvider;
gatewayURL: string;
bridge: string;
storage: BridgeStorage;
chainId: string;
};
Binary file added src/handlers/secret/contract.wasm.gz
Binary file not shown.
41 changes: 41 additions & 0 deletions src/handlers/secret/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { readFile } from "fs/promises";
import {
encodeSecp256k1Pubkey,
encodeSecp256k1Signature,
Expand Down Expand Up @@ -50,6 +51,46 @@ export function secretHandler({
);
return tx;
},
async deployCollection(signer, da, ga) {
const stored = await signer.tx.compute.storeCode(
{
wasm_byte_code: await readFile("./contract.wasm.gz"),
sender: "",
builder: "",
source: "",
},
{
...ga,
},
);
const code = stored.arrayLog?.find((e) => e.key === "code_id")?.value;
if (!code) {
throw new Error("Code not found");
}
const contract = await signer.tx.compute.instantiateContract(
{
code_id: code,
init_msg: {
name: da.name,
symbol: da.symbol,
owner: signer.address,
config: {
public_token_supply: true,
},
},
init_funds: [],
sender: signer.address,
label: `${da.name}-${Date.now()}`,
},
{
...ga,
},
);
const contractAddress = contract.arrayLog?.find(
(log) => log.type === "message" && log.key === "contract_address",
)?.value;
return contractAddress ?? raise("Contract not found");
},
mintNft(signer, ma) {
const mint = signer.tx.snip721.mint({
contract_address: ma.contractAddress,
Expand Down
10 changes: 8 additions & 2 deletions src/handlers/secret/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SecretNetworkClient, TxOptions, TxResponse } from "secretjs";
import { BridgeStorage } from "../../contractsTypes/evm";
import { MintNft, TNftChain } from "../types";
import { DeployCollection, MintNft, TNftChain } from "../types";

export type TSecretClaimArgs = {
token_id: string;
Expand Down Expand Up @@ -32,7 +32,13 @@ export type TSecretHandler = TNftChain<
TxResponse,
SecretNetworkClient
> &
MintNft<SecretNetworkClient, SecretMintArgs, TxResponse>;
MintNft<SecretNetworkClient, SecretMintArgs, TxResponse> &
DeployCollection<
SecretNetworkClient,
{ name: string; symbol: string },
TxOptions,
string
>;

export type TSecretParams = {
provider: SecretNetworkClient;
Expand Down
17 changes: 17 additions & 0 deletions src/handlers/tezos/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { BridgeContractType } from "../../contractsTypes/tezos/Bridge.types";
import { NFTContractType } from "../../contractsTypes/tezos/NFT.types";
import { address, tas } from "../../contractsTypes/tezos/type-aliases";

import { MichelsonMap } from "@taquito/taquito";
import { NFTCode } from "../../contractsTypes/tezos/NFT.code";
import { raise } from "../ton";
import { TTezosHandler, TTezosParams } from "./types";

Expand Down Expand Up @@ -132,6 +134,21 @@ export function tezosHandler({
.send();
return tx;
},
async deployCollection(signer, _da, ga) {
Tezos.setSignerProvider(signer);
const tx = await Tezos.contract.originate({
code: NFTCode.code,
storage: {
ledger: new MichelsonMap(),
operators: new MichelsonMap(),
token_metadata: new MichelsonMap(),
metadata: new MichelsonMap(),
admin: tas.address(await Tezos.signer.publicKeyHash()),
},
gasLimit: ga?.gasLimit,
});
return tx.contractAddress ?? raise("No contract address found");
},
async claimNft(signer, data, extraArgs, sigs) {
const isTezosAddr =
validateAddress(data.source_nft_contract_address) === 3;
Expand Down
5 changes: 3 additions & 2 deletions src/handlers/tezos/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Signer } from "@taquito/taquito";
import BigNumber from "bignumber.js";
import { BridgeStorage } from "../../contractsTypes/evm";
import { address, mutez, nat } from "../../contractsTypes/tezos/type-aliases";
import { MintNft, TSingularNftChain } from "../types";
import { DeployCollection, MintNft, TSingularNftChain } from "../types";

export type TTezosClaimArgs = {
token_id: nat;
Expand Down Expand Up @@ -40,7 +40,8 @@ export type TTezosHandler = TSingularNftChain<
TransactionOperation,
TezosToolkit
> &
MintNft<Signer, TezosMintArgs, TransactionOperation>;
MintNft<Signer, TezosMintArgs, TransactionOperation> &
DeployCollection<Signer, object, { gasLimit?: number }, string>;

export type TTezosParams = {
Tezos: TezosToolkit;
Expand Down
7 changes: 7 additions & 0 deletions src/handlers/ton/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ export function tonHandler({
},
);
},
async deployCollection(signer, da) {
const nft = new TonNftCollection(da);

nft.deploy(signer);

return nft.address.toString();
},
async getClaimData(txHash) {
const tx = await client.getTransaction(bridge.address, "", txHash);
if (!tx) {
Expand Down
5 changes: 3 additions & 2 deletions src/handlers/ton/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Sender } from "@ton/core";
import { TonClient } from "@ton/ton";
import { BridgeStorage } from "../../contractsTypes/evm";
import { ClaimData } from "../../contractsTypes/ton/tonBridge";
import { MintNft, TSingularNftChain } from "../types";
import { DeployCollection, MintNft, TSingularNftChain } from "../types";
import { collectionData } from "./nft";

export type TonMintArgs = collectionData;
Expand All @@ -14,7 +14,8 @@ export type TTonHandler = TSingularNftChain<
undefined,
TonClient
> &
MintNft<Sender, TonMintArgs, undefined>;
MintNft<Sender, TonMintArgs, undefined> &
DeployCollection<Sender, TonMintArgs, never, string>;

export type TTonParams = {
client: TonClient;
Expand Down
8 changes: 8 additions & 0 deletions src/handlers/types/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ export type MintNft<Signer, MintArgs, RetTx> = {
mintNft(signer: Signer, ma: MintArgs): Promise<RetTx>;
};

export type DeployCollection<Signer, DeployArgs, GasArgs, RetTx> = {
deployCollection(
signer: Signer,
da: DeployArgs,
ga: GasArgs | undefined,
): Promise<RetTx>;
};

/**
* Represents a function that locks an NFT on the chain inside the bridge smart contract.
* @template Signer The type of the signer. ie {Signer} on EVM from ethers
Expand Down

0 comments on commit c3e29e6

Please sign in to comment.