diff --git a/contracts.json b/contracts.json index 7d828d092..7a0fede57 100644 --- a/contracts.json +++ b/contracts.json @@ -1,12 +1,11 @@ { - "goerli": {}, - "sepolia": {}, + "testnet": {}, "mainnet": {}, - "local": { - "messaging": "0x385ac975687520f0b47f16aa619efb454d16c02388fd01b2fc36c7cb9235dc0", - "executor": "0x72edc1c4893cf4288b1f424b677e7f7c791def1c9826b615864821951875186", - "nftContract": "0x7a0d668105724f2db5197b353538af0454dd059cd0282444c22978493cf2acb", + "dev": { + "nftContract": "0x8305f69a64d04e908b957087411f26658a05ec35acf11afa9f9748b0783825", "eth": "0x172ca09df59789985a1dfb68e0f3f554121eb313c68cf391bd78f9bf69abcf", + "messaging": "0x7504defaee0ff49d1ac5afa45167da77cce68c4a62295aa9cfa35c83fc11e63", + "executor": "0x7fd31172080d3546c055c490c4b795589104aee02656bc4349573f2ac8cc21f", "orderbook": "0x3b08fc57e1fc53c8545fa799c7af60bf18b9f43dce739c24bf95f2f118da97" } } diff --git a/crates/solis/messaging.local.json b/crates/solis/messaging.local.json index e81b2abfd..08955ea0e 100644 --- a/crates/solis/messaging.local.json +++ b/crates/solis/messaging.local.json @@ -1,7 +1,7 @@ { "chain": "starknet", "rpc_url": "http://127.0.0.1:5050", - "contract_address": "0x385ac975687520f0b47f16aa619efb454d16c02388fd01b2fc36c7cb9235dc0", + "contract_address": "0x7504defaee0ff49d1ac5afa45167da77cce68c4a62295aa9cfa35c83fc11e63", "sender_address": "0x765149d6bc63271df7b0316537888b81aa021523f9516a05306f10fd36914da", "private_key": "0x1c9053c053edf324aec366a34c6901b1095b07af69495bffec7d7fe21effb1b", "interval": 2, diff --git a/packages/core/.env.example b/packages/core/.env.example index 8832bd4d4..e1916d1a4 100644 --- a/packages/core/.env.example +++ b/packages/core/.env.example @@ -12,7 +12,4 @@ STARKNET_ACCOUNT2_ADDRESS=0x5686a647a9cdd63ade617e0baf3b364856b813b508f03903eb58 STARKNET_ACCOUNT2_PRIVATE_KEY=0x33003003001800009900180300d206308b0070db00121318d17b5e6262150b STARKNET_ACCOUNT2_PUBLIC_KEY=0x4c0f884b8e5b4f00d97a3aad26b2e5de0c0c76a555060c837da2e287403c01d -# Starknet network -STARKNET_NETWORK_ID=local -# Solis network -SOLIS_NETWORK_ID=local +NETWORK=dev \ No newline at end of file diff --git a/packages/core/examples/cancelListing.ts b/packages/core/examples/cancelListing.ts index 410627cca..da845dd6d 100644 --- a/packages/core/examples/cancelListing.ts +++ b/packages/core/examples/cancelListing.ts @@ -12,8 +12,9 @@ import { } from "../src/actions/account/account"; import { cancelOrder, createListing } from "../src/actions/order"; import { getOrderHash, getOrderStatus } from "../src/actions/read"; -import { STARKNET_NFT_ADDRESS } from "../src/constants"; +import { Network } from "../src/constants"; import { ListingV1 } from "../src/types"; +import { getExampleNFTAddress } from "./constants"; // Initialize the RPC provider with the ArkChain node URL const starknetProvider = new RpcProvider({ @@ -25,12 +26,18 @@ const arkProvider = new RpcProvider({ nodeUrl: process.env.ARKCHAIN_RPC_URL ?? "http://0.0.0.0:7777" }); +const network = (process.env.NETWORK ?? "dev") as Network; + /** * Creates a listing on the blockchain using provided order details. * * @param {RpcProvider} provider - The RPC provider instance. */ -(async (arkProvider: RpcProvider, starknetProvider: RpcProvider) => { +(async ( + network: Network, + arkProvider: RpcProvider, + starknetProvider: RpcProvider +) => { // Create a new account using the provider const { account: arkAccount } = await createAccount(arkProvider); const starknetAccount = await fetchOrCreateAccount( @@ -39,6 +46,8 @@ const arkProvider = new RpcProvider({ process.env.ACCOUNT1_PRIVATE_KEY ); + const STARKNET_NFT_ADDRESS = getExampleNFTAddress(network); + // Define the order details let order: ListingV1 = { brokerId: 123, // The broker ID @@ -49,7 +58,7 @@ const arkProvider = new RpcProvider({ console.log("Creating listing order..."); // Create the listing on the arkchain using the order details - await createListing(arkProvider, starknetAccount, arkAccount, order); + await createListing(network, arkProvider, starknetAccount, arkAccount, order); // wait 5 seconds for the transaction to be processed await new Promise((resolve) => setTimeout(resolve, 5000)); @@ -58,11 +67,13 @@ const arkProvider = new RpcProvider({ const { orderHash } = await getOrderHash( order.tokenId, order.tokenAddress, + network, arkProvider ); let { orderStatus: orderStatusBefore } = await getOrderStatus( orderHash, + network, arkProvider ); console.log("orderStatus", shortString.decodeShortString(orderStatusBefore)); @@ -75,13 +86,14 @@ const arkProvider = new RpcProvider({ }; // Cancel the order - cancelOrder(arkProvider, starknetAccount, arkAccount, cancelInfo); + cancelOrder(network, arkProvider, starknetAccount, arkAccount, cancelInfo); await new Promise((resolve) => setTimeout(resolve, 2000)); let { orderStatus: orderStatusAfter } = await getOrderStatus( orderHash, + network, arkProvider ); console.log("orderStatus", shortString.decodeShortString(orderStatusAfter)); -})(arkProvider, starknetProvider); +})(network, arkProvider, starknetProvider); diff --git a/packages/core/examples/constants/contracts.ts b/packages/core/examples/constants/contracts.ts new file mode 100644 index 000000000..873543da2 --- /dev/null +++ b/packages/core/examples/constants/contracts.ts @@ -0,0 +1,5 @@ + + export const STARKNET_NFT_ADDRESS_MAINNET = ""; + export const STARKNET_NFT_ADDRESS_TESTNET = ""; + export const STARKNET_NFT_ADDRESS_DEV = "0x8305f69a64d04e908b957087411f26658a05ec35acf11afa9f9748b0783825"; + \ No newline at end of file diff --git a/packages/core/examples/constants/index.ts b/packages/core/examples/constants/index.ts new file mode 100644 index 000000000..ac390b39e --- /dev/null +++ b/packages/core/examples/constants/index.ts @@ -0,0 +1,16 @@ +import { Network } from "../../src"; +import { + STARKNET_NFT_ADDRESS_DEV, + STARKNET_NFT_ADDRESS_MAINNET, + STARKNET_NFT_ADDRESS_TESTNET +} from "./contracts"; + +const NETWORK_TO_ADDRESS_MAP = { + mainnet: STARKNET_NFT_ADDRESS_MAINNET, + testnet: STARKNET_NFT_ADDRESS_TESTNET, + dev: STARKNET_NFT_ADDRESS_DEV +}; + +export function getExampleNFTAddress(network: Network) { + return NETWORK_TO_ADDRESS_MAP[network]; +} diff --git a/packages/core/examples/createListing.ts b/packages/core/examples/createListing.ts index cf14b3702..0cbdd9fb9 100644 --- a/packages/core/examples/createListing.ts +++ b/packages/core/examples/createListing.ts @@ -12,8 +12,9 @@ import { } from "../src/actions/account/account"; import { createListing } from "../src/actions/order"; import { getOrderHash, getOrderStatus } from "../src/actions/read"; -import { STARKNET_NFT_ADDRESS } from "../src/constants"; +import { getContractAddresses, Network } from "../src/constants"; import { ListingV1 } from "../src/types"; +import { getExampleNFTAddress } from "./constants"; // Initialize the RPC provider with the ArkChain node URL const starknetProvider = new RpcProvider({ @@ -25,29 +26,20 @@ const arkProvider = new RpcProvider({ nodeUrl: process.env.ARKCHAIN_RPC_URL ?? "http://0.0.0.0:7777" }); -const katana0 = { - privateKey: "0x1800000000300000180000000000030000000000003006001800006600", - publicKey: - "0x2b191c2f3ecf685a91af7cf72a43e7b90e2e41220175de5c4f7498981b10053", - accountAddress: - "0x517ececd29116499f4a1b64b094da79ba08dfd54a3edaa316134c41f8160973" -}; - -const katana1 = { - privateKey: - "0x33003003001800009900180300d206308b0070db00121318d17b5e6262150b", - publicKey: - "0x4c0f884b8e5b4f00d97a3aad26b2e5de0c0c76a555060c837da2e287403c01d", - accountAddress: - "0x5686a647a9cdd63ade617e0baf3b364856b813b508f03903eb58a7e622d5855" -}; +const network = (process.env.NETWORK ?? "dev") as Network; /** * Creates a listing on the blockchain using provided order details. * * @param {RpcProvider} provider - The RPC provider instance. */ -(async (arkProvider: RpcProvider, starknetProvider: RpcProvider) => { +(async ( + network: Network, + arkProvider: RpcProvider, + starknetProvider: RpcProvider +) => { + const STARKNET_NFT_ADDRESS = getExampleNFTAddress(network); + // Create a new account using the provider const { account: arkAccount } = await createAccount(arkProvider); const starknetAccount = await fetchOrCreateAccount( @@ -64,18 +56,20 @@ const katana1 = { }; // Create the listing on the blockchain using the order details - await createListing(arkProvider, starknetAccount, arkAccount, order); + await createListing(network, arkProvider, starknetAccount, arkAccount, order); await new Promise((resolve) => setTimeout(resolve, 2000)); // Get the order hash const { orderHash } = await getOrderHash( order.tokenId, order.tokenAddress, + network, arkProvider ); let { orderStatus: orderStatusAfter } = await getOrderStatus( orderHash, + network, arkProvider ); console.log("orderStatus", shortString.decodeShortString(orderStatusAfter)); -})(arkProvider, starknetProvider); +})(network, arkProvider, starknetProvider); diff --git a/packages/core/examples/createOffer.ts b/packages/core/examples/createOffer.ts index a2a76c67b..3f878d262 100644 --- a/packages/core/examples/createOffer.ts +++ b/packages/core/examples/createOffer.ts @@ -6,6 +6,7 @@ import { RpcProvider } from "starknet"; +import { Network } from "../src"; import { createAccount, fetchOrCreateAccount @@ -23,12 +24,18 @@ const arkProvider = new RpcProvider({ nodeUrl: process.env.ARKCHAIN_RPC_URL ?? "http://0.0.0.0:7777" }); +const network = (process.env.NETWORK ?? "dev") as Network; + /** * Creates a listing on the blockchain using provided order details. * * @param {RpcProvider} provider - The RPC provider instance. */ -(async (arkProvider: RpcProvider, starknetProvider: RpcProvider) => { +(async ( + network: Network, + arkProvider: RpcProvider, + starknetProvider: RpcProvider +) => { // Create a new account using the provider const { account: arkAccount } = await createAccount(arkProvider); const starknetAccount = await fetchOrCreateAccount( @@ -48,5 +55,5 @@ const arkProvider = new RpcProvider({ // Create the listing on the blockchain using the order details console.log("Creating listing order..."); - await createOffer(arkProvider, starknetAccount, arkAccount, order); -})(arkProvider, starknetProvider); + await createOffer(network, arkProvider, starknetAccount, arkAccount, order); +})(network, arkProvider, starknetProvider); diff --git a/packages/core/examples/fulfillListing.ts b/packages/core/examples/fulfillListing.ts index 9b5661d1c..6807fae08 100644 --- a/packages/core/examples/fulfillListing.ts +++ b/packages/core/examples/fulfillListing.ts @@ -20,12 +20,9 @@ import { import { approveERC20, approveERC721 } from "../src/actions/contract"; import { createListing, fulfillListing } from "../src/actions/order"; import { getOrderHash, getOrderStatus } from "../src/actions/read"; -import { - STARKNET_ETH_ADDRESS, - STARKNET_EXECUTOR_ADDRESS, - STARKNET_NFT_ADDRESS -} from "../src/constants"; -import { ListingV1 } from "../src/types"; +import { getContractAddresses } from "../src/constants"; +import { ListingV1, Network } from "../src/types"; +import { getExampleNFTAddress } from "./constants"; // Initialize the RPC provider with the ArkChain node URL const starknetProvider = new RpcProvider({ @@ -37,13 +34,16 @@ const arkProvider = new RpcProvider({ nodeUrl: process.env.ARKCHAIN_RPC_URL || "" }); +const network = (process.env.NETWORK ?? "dev") as Network; + async function freeMint( + contractAddress: string, provider: RpcProvider, starknetAccount: Account, tokenId: BigNumberish ) { const mintResult = await starknetAccount.execute({ - contractAddress: STARKNET_NFT_ADDRESS, + contractAddress, entrypoint: "mint", calldata: CallData.compile({ recipient: starknetAccount.address, @@ -58,19 +58,24 @@ async function freeMint( * * @param {RpcProvider} provider - The RPC provider instance. */ -(async (arkProvider: RpcProvider, starknetProvider: RpcProvider) => { +(async ( + network: Network, + arkProvider: RpcProvider, + starknetProvider: RpcProvider +) => { console.log("=> process.env.ARKCHAIN_RPC_URL", process.env.ARKCHAIN_RPC_URL); // Create a new account for the listing using the provider const { account: arkAccount } = await createAccount(arkProvider); - - console.log("STARKNET_NFT_ADDRESS:", STARKNET_NFT_ADDRESS); + const STARKNET_NFT_ADDRESS = getExampleNFTAddress(network); + const { STARKNET_EXECUTOR_ADDRESS, STARKNET_ETH_ADDRESS } = + getContractAddresses(network); // Define the order details let order: ListingV1 = { brokerId: 123, // The broker ID tokenAddress: STARKNET_NFT_ADDRESS, // The token address - tokenId: 5, // The ID of the token + tokenId: 16, // The ID of the token startAmount: 100000000000000000 // The starting amount for the order }; @@ -81,7 +86,12 @@ async function freeMint( ); console.log("Minting token...", STARKNET_NFT_ADDRESS); - await freeMint(starknetProvider, starknetOffererAccount, order.tokenId); + await freeMint( + STARKNET_NFT_ADDRESS, + starknetProvider, + starknetOffererAccount, + order.tokenId + ); console.log( `Approving token ${order.tokenId} to ${STARKNET_EXECUTOR_ADDRESS}...` @@ -96,7 +106,13 @@ async function freeMint( console.log("Creating listing..."); // Create the listing on the arkchain using the order details - await createListing(arkProvider, starknetOffererAccount, arkAccount, order); + await createListing( + network, + arkProvider, + starknetOffererAccount, + arkAccount, + order + ); // wait 5 seconds for the transaction to be processed await new Promise((resolve) => setTimeout(resolve, 2000)); @@ -105,6 +121,7 @@ async function freeMint( const { orderHash } = await getOrderHash( order.tokenId, order.tokenAddress, + network, arkProvider ); @@ -149,6 +166,7 @@ async function freeMint( // Cancel the order fulfillListing( + network, arkProvider, starknetFulfillerAccount, arkAccount, @@ -158,7 +176,8 @@ async function freeMint( let { orderStatus: orderStatusAfter } = await getOrderStatus( orderHash, + network, arkProvider ); console.log("orderStatus", shortString.decodeShortString(orderStatusAfter)); -})(arkProvider, starknetProvider); +})(network, arkProvider, starknetProvider); diff --git a/packages/core/examples/fulfillOffer.ts b/packages/core/examples/fulfillOffer.ts index 60dceaf5d..f7354bb06 100644 --- a/packages/core/examples/fulfillOffer.ts +++ b/packages/core/examples/fulfillOffer.ts @@ -11,6 +11,7 @@ import { createOffer, fulfillOffer, getOrderStatus, + Network, OfferV1 } from "../src"; import { fetchOrCreateAccount } from "../src/actions/account/account"; @@ -25,12 +26,18 @@ const arkProvider = new RpcProvider({ nodeUrl: process.env.ARKCHAIN_RPC_URL ?? "http://0.0.0.0:7777" }); +const network = (process.env.NETWORK ?? "dev") as Network; + /** * Creates a listing on the blockchain using provided order details. * * @param {RpcProvider} provider - The RPC provider instance. */ -(async (arkProvider: RpcProvider, starknetProvider: RpcProvider) => { +(async ( + network: Network, + arkProvider: RpcProvider, + starknetProvider: RpcProvider +) => { // Create a new account for the listing using the provider const { account: arkAccount } = await createAccount(arkProvider); const starknetAccount = await fetchOrCreateAccount( @@ -50,6 +57,7 @@ const arkProvider = new RpcProvider({ // Create the listing on the arkchain using the order details let orderHash = await createOffer( + network, arkProvider, starknetAccount, arkAccount, @@ -61,6 +69,7 @@ const arkProvider = new RpcProvider({ let { orderStatus: orderStatusBefore } = await getOrderStatus( orderHash, + network, arkProvider ); console.log("orderStatus", shortString.decodeShortString(orderStatusBefore)); @@ -80,13 +89,14 @@ const arkProvider = new RpcProvider({ }; // Cancel the order - fulfillOffer(arkProvider, fulfillerAccount, arkAccount, fulfillInfo); + fulfillOffer(network, arkProvider, fulfillerAccount, arkAccount, fulfillInfo); await new Promise((resolve) => setTimeout(resolve, 2000)); let { orderStatus: orderStatusAfter } = await getOrderStatus( orderHash, + network, arkProvider ); console.log("orderStatus", shortString.decodeShortString(orderStatusAfter)); -})(arkProvider, starknetProvider); +})(network, arkProvider, starknetProvider); diff --git a/packages/core/examples/test.ts b/packages/core/examples/test.ts deleted file mode 100644 index 82922a9d5..000000000 --- a/packages/core/examples/test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import * as dotenv from "dotenv"; -import { cairo, CallData, RpcProvider } from "starknet"; - -import { fetchOrCreateAccount } from "../src/actions/account/account"; -import { approveERC20 } from "../src/actions/contract"; -import { - STARKNET_ADMIN_ACCOUNT_ADDRESS, - STARKNET_ETH_ADDRESS, - STARKNET_EXECUTOR_ADDRESS -} from "../src/constants"; - -dotenv.config(); - -const starknetProvider = new RpcProvider({ - nodeUrl: process.env.STARKNET_RPC_URL || "" -}); - -(async () => { - const makerAddress = await fetchOrCreateAccount( - starknetProvider, - process.env.ACCOUNT1_ADDRESS, - process.env.ACCOUNT1_PRIVATE_KEY - ); - - const starknetFulfillerAccount = await fetchOrCreateAccount( - starknetProvider, - process.env.ACCOUNT2_ADDRESS, - process.env.ACCOUNT2_PRIVATE_KEY - ); - - // console.log("Minting ETH..."); - // const mintResult = await starknetFulfillerAccount.execute({ - // contractAddress: STARKNET_ETH_ADDRESS, - // entrypoint: "mint", - // calldata: CallData.compile({ - // recipient: starknetFulfillerAccount.address, - // amount: cairo.uint256(10000000000000000000) - // }) - // }); - // await starknetProvider.waitForTransaction(mintResult.transaction_hash); - - const balanceOf = await starknetFulfillerAccount.callContract({ - contractAddress: STARKNET_ETH_ADDRESS, - entrypoint: "balance_of", - calldata: CallData.compile({ - account: starknetFulfillerAccount.address - }) - }); - - console.log("=> Balance:", balanceOf.result.toString()); - - await approveERC20( - starknetProvider, - starknetFulfillerAccount, - STARKNET_ETH_ADDRESS, - starknetFulfillerAccount.address, - BigInt(100) - ); - - // from => "0x05686a647a9cdd63ade617e0baf3b364856b813b508f03903eb58a7e622d5855", - // to => "0x0517ececd29116499f4a1b64b094da79ba08dfd54a3edaa316134c41f8160973", - // ethContract => "0x0461003257aec8b23c6d338ab1a4a0ea0afb35fae83abd3cd87087b6310644fb" - - // const result = await starknetFulfillerAccount.execute({ - // contractAddress: STARKNET_ETH_ADDRESS, - // entrypoint: "transfer_from", - // calldata: CallData.compile({ - // sender: starknetFulfillerAccount.address, - // recipient: makerAddress.address, - // amount: cairo.uint256(1) - // }) - // }); - - const result = await starknetFulfillerAccount.execute({ - contractAddress: STARKNET_EXECUTOR_ADDRESS, - entrypoint: "swap_eth", - calldata: CallData.compile({ - from: starknetFulfillerAccount.address, - to: makerAddress.address, - amount: cairo.uint256(1), - payment_currency_address: STARKNET_ETH_ADDRESS - }) - }); - - await starknetProvider.waitForTransaction(result.transaction_hash); - console.log("=> done"); -})(); diff --git a/packages/core/package.json b/packages/core/package.json index 38b3838db..10deb39af 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -8,7 +8,8 @@ "clean": "rm -rf .turbo node_modules", "lint": "eslint . --max-warnings 0", "type-check": "tsc --noEmit", - "build": "tsup src/index.ts --format cjs,esm --dts", + "build:constants": "npx ts-node ./scripts/build.ts", + "build": "pnpm run build:constants && tsup src/index.ts --format cjs,esm --dts", "test": "mocha --require ts-node/register --timeout 10000 'tests/**/*.ts'" }, "dependencies": { @@ -16,8 +17,6 @@ "@types/chai-as-promised": "^7.1.8", "commander": "^11.1.0", "dotenv": "^16.3.1", - "fs": "0.0.1-security", - "i": "^0.3.7", "npm": "^10.2.4", "path": "^0.12.7", "starknet": "5.22.0" diff --git a/packages/core/scripts/build.ts b/packages/core/scripts/build.ts new file mode 100644 index 000000000..9e692160b --- /dev/null +++ b/packages/core/scripts/build.ts @@ -0,0 +1,90 @@ +import fs from "fs"; +import path from "path"; + +type ContractConfig = { + [key: string]: { + messaging?: string; + executor?: string; + nftContract?: string; + eth?: string; + orderbook?: string; + }; +}; + +const CONTRACTS_JSON_PATH = path.join(__dirname, "..", "../../contracts.json"); +const CONTRACTS_TS_PATH = path.join( + __dirname, + "..", + "src/constants/contracts.ts" +); +const EXAMPLES_CONTRACTS_TS_PATH = path.join( + __dirname, + "..", + "examples/constants/contracts.ts" +); + +const NETWORKS = { + testnet: "goerli", // TODO: change to sepolia + mainnet: "mainnet", + dev: "dev" +}; + +const readJson = (filePath: string): ContractConfig => { + const rawJson = fs.readFileSync(filePath, "utf8"); + return JSON.parse(rawJson); +}; + +const constructContractConstants = ( + contracts: ContractConfig, + network: string, + networkName: string +): string => + ` +export const STARKNET_ETH_ADDRESS_${networkName} = "${ + contracts[network]?.eth || "" + }"; +export const STARKNET_NFT_ADDRESS_${networkName} = "${ + contracts[network]?.nftContract || "" + }"; +export const STARKNET_EXECUTOR_ADDRESS_${networkName} = "${ + contracts[network]?.executor || "" + }"; +export const SOLIS_ORDER_BOOK_ADDRESS_${networkName} = "${ + contracts[network]?.orderbook || "" + }"; +`.trim(); + +const constructAllConstants = (contracts: ContractConfig) => + Object.entries(NETWORKS) + .map(([networkName, network]) => + constructContractConstants(contracts, network, networkName.toUpperCase()) + ) + .join("\n\n"); + +const writeToFile = (filePath: string, data: string) => { + fs.writeFileSync(filePath, data); +}; + +// Main execution +try { + const contracts = readJson(CONTRACTS_JSON_PATH); + const contractConstants = constructAllConstants(contracts); + + writeToFile(CONTRACTS_TS_PATH, contractConstants); + writeToFile( + EXAMPLES_CONTRACTS_TS_PATH, + ` + export const STARKNET_NFT_ADDRESS_MAINNET = "${ + contracts.mainnet?.nftContract || "" + }"; + export const STARKNET_NFT_ADDRESS_TESTNET = "${ + contracts.goerli?.nftContract || "" + }"; + export const STARKNET_NFT_ADDRESS_DEV = "${ + contracts.dev?.nftContract || "" + }"; + ` + ); +} catch (error) { + console.error("An error occurred:", error); +} diff --git a/packages/core/src/actions/contract/approve.ts b/packages/core/src/actions/contract/approve.ts index 6167e1658..f233eeae5 100644 --- a/packages/core/src/actions/contract/approve.ts +++ b/packages/core/src/actions/contract/approve.ts @@ -1,19 +1,38 @@ import { Account, + AccountInterface, cairo, CallData, + ProviderInterface, RpcProvider, type BigNumberish } from "starknet"; - export const approveERC721 = async ( - provider: RpcProvider, - account: Account, + provider: ProviderInterface, + account: AccountInterface, contractAddress: string, to: BigNumberish, tokenId: BigNumberish ) => { + // console.log("contractAddress", contractAddress); + + // const { abi: testAbi } = await provider.getClassAt(contractAddress); + // if (testAbi === undefined) { + // throw new Error("no abi."); + // } + // console.log(testAbi); + + // const isApproved = await account.callContract({ + // contractAddress, + // entrypoint: "get_approved", + // calldata: CallData.compile({ + // token_id: cairo.uint256(tokenId) + // }) + // }); + + // console.log("=> isApproved", isApproved); + const result = await account.execute({ contractAddress, entrypoint: "approve", diff --git a/packages/core/src/actions/order/_create.ts b/packages/core/src/actions/order/_create.ts index e77f6fbd1..8e9318c55 100644 --- a/packages/core/src/actions/order/_create.ts +++ b/packages/core/src/actions/order/_create.ts @@ -7,9 +7,9 @@ import { RpcProvider } from "starknet"; -import { SOLIS_ORDER_BOOK_ADDRESS } from "../../constants"; +import { getContractAddresses } from "../../constants"; import { getSignInfos } from "../../signer"; -import { OrderV1 } from "../../types"; +import { Network, OrderV1 } from "../../types"; import { getOrderHashFromOrderV1 } from "../../utils"; /** @@ -23,6 +23,7 @@ import { getOrderHashFromOrderV1 } from "../../utils"; * @throws {Error} Throws an error if the ABI or order type is invalid. */ const createOrder = async ( + network: Network, arkProvider: RpcProvider, starknetAccount: AccountInterface, arkAccount: Account, @@ -64,6 +65,8 @@ const createOrder = async ( signer: signer }); + const { SOLIS_ORDER_BOOK_ADDRESS } = getContractAddresses(network); + // Execute the transaction const result = await arkAccount.execute({ contractAddress: SOLIS_ORDER_BOOK_ADDRESS, diff --git a/packages/core/src/actions/order/_fulfill.ts b/packages/core/src/actions/order/_fulfill.ts index 0bebd2f63..d9915b484 100644 --- a/packages/core/src/actions/order/_fulfill.ts +++ b/packages/core/src/actions/order/_fulfill.ts @@ -7,9 +7,9 @@ import { RpcProvider } from "starknet"; -import { SOLIS_ORDER_BOOK_ADDRESS } from "../../constants"; +import { getContractAddresses } from "../../constants"; import { getSignInfos } from "../../signer"; -import { FulfillInfo } from "../../types"; +import { FulfillInfo, Network } from "../../types"; /** * Creates an order on the Arkchain with specific constraints based on order type. @@ -22,6 +22,7 @@ import { FulfillInfo } from "../../types"; * @throws {Error} Throws an error if the ABI or order type is invalid. */ export const _fulfillOrder = async ( + network: Network, provider: RpcProvider, starknetFulfillerAccount: AccountInterface, arkFulfillerAccount: Account, @@ -68,6 +69,8 @@ export const _fulfillOrder = async ( signer: signer }); + const { SOLIS_ORDER_BOOK_ADDRESS } = getContractAddresses(network); + // Execute the transaction const result = await arkFulfillerAccount.execute({ contractAddress: SOLIS_ORDER_BOOK_ADDRESS, diff --git a/packages/core/src/actions/order/cancel.ts b/packages/core/src/actions/order/cancel.ts index 50db535cd..4757ee5c0 100644 --- a/packages/core/src/actions/order/cancel.ts +++ b/packages/core/src/actions/order/cancel.ts @@ -12,11 +12,12 @@ import { Uint256 } from "starknet"; -import { SOLIS_ORDER_BOOK_ADDRESS } from "../../constants"; +import { getContractAddresses } from "../../constants"; import { getSignInfos } from "../../signer"; -import { CancelInfo, FullCancelInfo } from "../../types"; +import { CancelInfo, FullCancelInfo, Network } from "../../types"; const cancelOrder = async ( + network: Network, arkProvider: RpcProvider, starknetAccount: AccountInterface, arkAccount: Account, @@ -70,6 +71,8 @@ const cancelOrder = async ( signer: signer }); + const { SOLIS_ORDER_BOOK_ADDRESS } = getContractAddresses(network); + // Execute the transaction const result = await arkAccount.execute({ contractAddress: SOLIS_ORDER_BOOK_ADDRESS, diff --git a/packages/core/src/actions/order/createListing.ts b/packages/core/src/actions/order/createListing.ts index 5a310cf81..69938ea1b 100644 --- a/packages/core/src/actions/order/createListing.ts +++ b/packages/core/src/actions/order/createListing.ts @@ -9,11 +9,8 @@ import { Uint256 } from "starknet"; -import { - SOLIS_ORDER_BOOK_ADDRESS, - STARKNET_ETH_ADDRESS -} from "../../constants"; -import { ListingV1, OrderV1, RouteType } from "../../types"; +import { getContractAddresses } from "../../constants"; +import { ListingV1, Network, OrderV1, RouteType } from "../../types"; import { createOrder } from "./_create"; /** @@ -33,12 +30,16 @@ import { createOrder } from "./_create"; * @throws {Error} Throws an error if the ABI for the order book contract is not found. */ const createListing = async ( + network: Network, arkProvider: RpcProvider, starknetAccount: AccountInterface, arkAccount: Account, baseOrder: ListingV1, owner?: string ) => { + const { SOLIS_ORDER_BOOK_ADDRESS, STARKNET_ETH_ADDRESS } = + getContractAddresses(network); + // Retrieve the ABI for the order book contract const { abi: orderbookAbi } = await arkProvider.getClassAt( SOLIS_ORDER_BOOK_ADDRESS @@ -77,6 +78,7 @@ const createListing = async ( }; const orderHash = await createOrder( + network, arkProvider, starknetAccount, arkAccount, diff --git a/packages/core/src/actions/order/createOffer.ts b/packages/core/src/actions/order/createOffer.ts index 826098a5c..612be2e50 100644 --- a/packages/core/src/actions/order/createOffer.ts +++ b/packages/core/src/actions/order/createOffer.ts @@ -9,8 +9,8 @@ import { Uint256 } from "starknet"; -import { SOLIS_ORDER_BOOK_ADDRESS } from "../../constants"; -import { OfferV1, OrderV1, RouteType } from "../../types"; +import { getContractAddresses } from "../../constants"; +import { Network, OfferV1, OrderV1, RouteType } from "../../types"; import { createOrder } from "./_create"; /** @@ -30,12 +30,15 @@ import { createOrder } from "./_create"; * @throws {Error} Throws an error if the ABI for the order book contract is not found. */ const createOffer = async ( + network: Network, arkProvider: RpcProvider, starknetAccount: AccountInterface, arkAccount: Account, baseOrder: OfferV1, owner?: string ) => { + const { SOLIS_ORDER_BOOK_ADDRESS } = getContractAddresses(network); + // Retrieve the ABI for the order book contract const { abi: orderbookAbi } = await arkProvider.getClassAt( SOLIS_ORDER_BOOK_ADDRESS @@ -75,6 +78,7 @@ const createOffer = async ( additionalData: [45] }; const orderHash = await createOrder( + network, arkProvider, starknetAccount, arkAccount, diff --git a/packages/core/src/actions/order/fulfillListing.ts b/packages/core/src/actions/order/fulfillListing.ts index 0b40aa74a..a6f6fd381 100644 --- a/packages/core/src/actions/order/fulfillListing.ts +++ b/packages/core/src/actions/order/fulfillListing.ts @@ -10,10 +10,11 @@ import { Uint256 } from "starknet"; -import { FulfillInfo, FulfillListingInfo } from "../../types"; +import { FulfillInfo, FulfillListingInfo, Network } from "../../types"; import { _fulfillOrder } from "./_fulfill"; const fulfillListing = async ( + network: Network, arkProvider: RpcProvider, starknetFulfillerAccount: AccountInterface, arkFulfillerAccount: Account, @@ -33,6 +34,7 @@ const fulfillListing = async ( }; _fulfillOrder( + network, arkProvider, starknetFulfillerAccount, arkFulfillerAccount, diff --git a/packages/core/src/actions/order/fulfillOffer.ts b/packages/core/src/actions/order/fulfillOffer.ts index ff8975059..5875c94eb 100644 --- a/packages/core/src/actions/order/fulfillOffer.ts +++ b/packages/core/src/actions/order/fulfillOffer.ts @@ -10,10 +10,11 @@ import { Uint256 } from "starknet"; -import { FulfillInfo, FulfillOfferInfo } from "../../types"; +import { FulfillInfo, FulfillOfferInfo, Network } from "../../types"; import { _fulfillOrder } from "./_fulfill"; const fulfillOffer = async ( + network: Network, provider: RpcProvider, starknetFulfillerAccount: AccountInterface, arkFulfillerAccount: Account, @@ -33,6 +34,7 @@ const fulfillOffer = async ( }; _fulfillOrder( + network, provider, starknetFulfillerAccount, arkFulfillerAccount, diff --git a/packages/core/src/actions/read/getOrder.ts b/packages/core/src/actions/read/getOrder.ts index 2cf6b9682..2fed31193 100644 --- a/packages/core/src/actions/read/getOrder.ts +++ b/packages/core/src/actions/read/getOrder.ts @@ -1,8 +1,15 @@ import { BigNumberish, CallData, Contract, RpcProvider } from "starknet"; -import { SOLIS_ORDER_BOOK_ADDRESS } from "../../constants"; +import { getContractAddresses } from "../../constants"; +import { Network } from "../../types"; + +const getOrder = async ( + network: Network, + orderHash: BigNumberish, + provider: RpcProvider +) => { + const { SOLIS_ORDER_BOOK_ADDRESS } = getContractAddresses(network); -const getOrder = async (orderHash: BigNumberish, provider: RpcProvider) => { const { abi: orderbookAbi } = await provider.getClassAt( SOLIS_ORDER_BOOK_ADDRESS ); diff --git a/packages/core/src/actions/read/getOrderHash.ts b/packages/core/src/actions/read/getOrderHash.ts index 2802e47fd..119cae99b 100644 --- a/packages/core/src/actions/read/getOrderHash.ts +++ b/packages/core/src/actions/read/getOrderHash.ts @@ -8,11 +8,13 @@ import { shortString } from "starknet"; -import { SOLIS_ORDER_BOOK_ADDRESS } from "../../constants"; +import { getContractAddresses } from "../../constants"; +import { Network } from "../../types"; const getOrderHash = async ( tokenId: BigNumberish, tokenAddress: BigNumberish, + network: Network, provider: RpcProvider ) => { let tokenHash = { @@ -30,6 +32,8 @@ const getOrderHash = async ( const tokenHashMessage = starknet.poseidonHashMany(tokenHashBigIntArray); + const { SOLIS_ORDER_BOOK_ADDRESS } = getContractAddresses(network); + const { abi: orderbookAbi } = await provider.getClassAt( SOLIS_ORDER_BOOK_ADDRESS ); diff --git a/packages/core/src/actions/read/getOrderSigner.ts b/packages/core/src/actions/read/getOrderSigner.ts index abf1f1243..eecd9acf7 100644 --- a/packages/core/src/actions/read/getOrderSigner.ts +++ b/packages/core/src/actions/read/getOrderSigner.ts @@ -1,11 +1,15 @@ import { BigNumberish, CallData, Contract, RpcProvider } from "starknet"; -import { SOLIS_ORDER_BOOK_ADDRESS } from "../../constants"; +import { getContractAddresses } from "../../constants"; +import { Network } from "../../types"; const getOrderSigner = async ( + network: Network, orderHash: BigNumberish, provider: RpcProvider ) => { + const { SOLIS_ORDER_BOOK_ADDRESS } = getContractAddresses(network); + const { abi: orderbookAbi } = await provider.getClassAt( SOLIS_ORDER_BOOK_ADDRESS ); diff --git a/packages/core/src/actions/read/getOrderStatus.ts b/packages/core/src/actions/read/getOrderStatus.ts index 37be1ba0b..40da332f1 100644 --- a/packages/core/src/actions/read/getOrderStatus.ts +++ b/packages/core/src/actions/read/getOrderStatus.ts @@ -1,11 +1,15 @@ import { BigNumberish, CallData, Contract, RpcProvider } from "starknet"; -import { SOLIS_ORDER_BOOK_ADDRESS } from "../../constants"; +import { getContractAddresses } from "../../constants"; +import { Network } from "../../types"; const getOrderStatus = async ( orderHash: BigNumberish, + network: Network, provider: RpcProvider ) => { + const { SOLIS_ORDER_BOOK_ADDRESS } = getContractAddresses(network); + const { abi: orderbookAbi } = await provider.getClassAt( SOLIS_ORDER_BOOK_ADDRESS ); diff --git a/packages/core/src/actions/read/getOrderType.ts b/packages/core/src/actions/read/getOrderType.ts index 95c059df9..b6024ebc5 100644 --- a/packages/core/src/actions/read/getOrderType.ts +++ b/packages/core/src/actions/read/getOrderType.ts @@ -6,9 +6,16 @@ import { RpcProvider } from "starknet"; -import { SOLIS_ORDER_BOOK_ADDRESS } from "../../constants"; +import { getContractAddresses } from "../../constants"; +import { Network } from "../../types"; + +const getOrderType = async ( + orderHash: BigNumberish, + network: Network, + provider: RpcProvider +) => { + const { SOLIS_ORDER_BOOK_ADDRESS } = getContractAddresses(network); -const getOrderType = async (orderHash: BigNumberish, provider: RpcProvider) => { const { abi: orderbookAbi } = await provider.getClassAt( SOLIS_ORDER_BOOK_ADDRESS ); diff --git a/packages/core/src/constants.ts b/packages/core/src/constants.ts deleted file mode 100644 index e9adcfddb..000000000 --- a/packages/core/src/constants.ts +++ /dev/null @@ -1,42 +0,0 @@ -import fs from "fs"; -import path from "path"; - -type ContractConfig = { - [key: string]: { - messaging?: string; - executor?: string; - nftContract?: string; - eth?: string; - orderbook?: string; - }; -}; - -// Read contract.json -const contractJsonPath = path.join(__dirname, "..", "../../contracts.json"); -const contractJson = fs.readFileSync(contractJsonPath, "utf8"); -const contracts: ContractConfig = JSON.parse(contractJson); - -// Get the current networks from environment variables -const starknetNetwork = (process.env.STARKNET_NETWORK_ID || - "local") as keyof ContractConfig; -const solisNetwork = (process.env.SOLIS_NETWORK_ID || - "local") as keyof ContractConfig; - -// Assign constants based on the current networks -export const STARKNET_ORDER_BOOK_ADDRESS = - contracts[starknetNetwork]?.orderbook || ""; -export const STARKNET_ETH_ADDRESS = contracts[starknetNetwork]?.eth || ""; -export const STARKNET_NFT_ADDRESS = - contracts[starknetNetwork]?.nftContract || ""; -export const STARKNET_EXECUTOR_ADDRESS = - contracts[starknetNetwork]?.executor || ""; - -export const SOLIS_ORDER_BOOK_ADDRESS = - contracts[solisNetwork]?.orderbook || ""; -// Add other Solis constants as needed - -export const SOLIS_ACCOUNT_CLASS_HASH = - "0x04d07e40e93398ed3c76981e72dd1fd22557a78ce36c0515f679e27f0bb5bc5f"; - -export const STARKNET_ADMIN_ACCOUNT_ADDRESS = - "0x765149d6bc63271df7b0316537888b81aa021523f9516a05306f10fd36914da"; diff --git a/packages/core/src/constants/contracts.ts b/packages/core/src/constants/contracts.ts new file mode 100644 index 000000000..d43cf2b61 --- /dev/null +++ b/packages/core/src/constants/contracts.ts @@ -0,0 +1,14 @@ +export const STARKNET_ETH_ADDRESS_TESTNET = ""; +export const STARKNET_NFT_ADDRESS_TESTNET = ""; +export const STARKNET_EXECUTOR_ADDRESS_TESTNET = ""; +export const SOLIS_ORDER_BOOK_ADDRESS_TESTNET = ""; + +export const STARKNET_ETH_ADDRESS_MAINNET = ""; +export const STARKNET_NFT_ADDRESS_MAINNET = ""; +export const STARKNET_EXECUTOR_ADDRESS_MAINNET = ""; +export const SOLIS_ORDER_BOOK_ADDRESS_MAINNET = ""; + +export const STARKNET_ETH_ADDRESS_DEV = "0x172ca09df59789985a1dfb68e0f3f554121eb313c68cf391bd78f9bf69abcf"; +export const STARKNET_NFT_ADDRESS_DEV = "0x8305f69a64d04e908b957087411f26658a05ec35acf11afa9f9748b0783825"; +export const STARKNET_EXECUTOR_ADDRESS_DEV = "0x7fd31172080d3546c055c490c4b795589104aee02656bc4349573f2ac8cc21f"; +export const SOLIS_ORDER_BOOK_ADDRESS_DEV = "0x3b08fc57e1fc53c8545fa799c7af60bf18b9f43dce739c24bf95f2f118da97"; \ No newline at end of file diff --git a/packages/core/src/constants/index.ts b/packages/core/src/constants/index.ts new file mode 100644 index 000000000..22a7f6d0e --- /dev/null +++ b/packages/core/src/constants/index.ts @@ -0,0 +1,30 @@ +/* eslint-disable no-unused-vars */ +import { Network } from "../types"; +import * as contracts from "./contracts"; + +export const SOLIS_ACCOUNT_CLASS_HASH = + "0x04d07e40e93398ed3c76981e72dd1fd22557a78ce36c0515f679e27f0bb5bc5f"; +export const STARKNET_ADMIN_ACCOUNT_ADDRESS = + "0x765149d6bc63271df7b0316537888b81aa021523f9516a05306f10fd36914da"; + +const NETWORK_CONTRACT_ADDRESSES = { + [Network.Dev]: { + SOLIS_ORDER_BOOK_ADDRESS: contracts.SOLIS_ORDER_BOOK_ADDRESS_DEV, + STARKNET_ETH_ADDRESS: contracts.STARKNET_ETH_ADDRESS_DEV, + STARKNET_EXECUTOR_ADDRESS: contracts.STARKNET_EXECUTOR_ADDRESS_DEV + }, + [Network.Testnet]: { + SOLIS_ORDER_BOOK_ADDRESS: contracts.SOLIS_ORDER_BOOK_ADDRESS_TESTNET, + STARKNET_ETH_ADDRESS: contracts.STARKNET_ETH_ADDRESS_TESTNET, + STARKNET_EXECUTOR_ADDRESS: contracts.STARKNET_EXECUTOR_ADDRESS_TESTNET + }, + [Network.Mainnet]: { + SOLIS_ORDER_BOOK_ADDRESS: contracts.SOLIS_ORDER_BOOK_ADDRESS_MAINNET, + STARKNET_ETH_ADDRESS: contracts.STARKNET_ETH_ADDRESS_MAINNET, + STARKNET_EXECUTOR_ADDRESS: contracts.STARKNET_EXECUTOR_ADDRESS_MAINNET + } +}; + +export function getContractAddresses(network: Network) { + return NETWORK_CONTRACT_ADDRESSES[network]; +} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 32a9e65d8..07af5f355 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -16,6 +16,10 @@ export { getOrderType } from "./actions/read"; +export { approveERC20, approveERC721 } from "./actions/contract"; + export { initProvider } from "./provider/rpc"; -export type { ListingV1, OfferV1, RouteType } from "./types"; +export type { ListingV1, OfferV1, RouteType, Network } from "./types"; + +export { getContractAddresses } from "./constants"; diff --git a/packages/core/src/types/index.ts b/packages/core/src/types/index.ts index 6ee19ebb9..bad176988 100644 --- a/packages/core/src/types/index.ts +++ b/packages/core/src/types/index.ts @@ -66,3 +66,9 @@ export type BaseFulfillInfo = { export type FulfillListingInfo = BaseFulfillInfo; export type FulfillOfferInfo = BaseFulfillInfo; + +export enum Network { + Mainnet = "mainnet", + Testnet = "testnet", + Dev = "dev" +} diff --git a/packages/core/tests/cancelListing.test.ts b/packages/core/tests/cancelListing.test.ts index 938644076..03bce7656 100644 --- a/packages/core/tests/cancelListing.test.ts +++ b/packages/core/tests/cancelListing.test.ts @@ -8,7 +8,8 @@ import { createListing, getOrderHash, getOrderStatus, - ListingV1 + ListingV1, + Network } from "../src"; import { generateRandomTokenId, sleep } from "./utils"; // Assuming you have a sleep utility function @@ -26,6 +27,8 @@ describe("ArkProject Cancel listing", () => { nodeUrl: "http://0.0.0.0:7777" }); + const network = "dev" as Network; + // Create a new account using the provider const { account: arkAccount } = await createAccount(arkProvider); const { account: starknetAccount } = await createAccount(starknetProvider); @@ -43,13 +46,20 @@ describe("ArkProject Cancel listing", () => { }; // Create the listing on the arkchain using the order details - await createListing(arkProvider, starknetAccount, arkAccount, order); + await createListing( + network, + arkProvider, + starknetAccount, + arkAccount, + order + ); await sleep(1000); // Wait for the transaction to be processed // Get the order hash const { orderHash } = await getOrderHash( order.tokenId, order.tokenAddress, + network, arkProvider ); // Assert that we received an order hash @@ -57,7 +67,7 @@ describe("ArkProject Cancel listing", () => { // Assert that the order is open await expect( - getOrderStatus(orderHash, arkProvider).then((res) => + getOrderStatus(orderHash, network, arkProvider).then((res) => shortString.decodeShortString(res.orderStatus) ) ).to.eventually.equal("OPEN"); @@ -70,11 +80,11 @@ describe("ArkProject Cancel listing", () => { }; // Cancel the order - cancelOrder(arkProvider, starknetAccount, arkAccount, cancelInfo); + cancelOrder(network, arkProvider, starknetAccount, arkAccount, cancelInfo); await sleep(1000); // Wait for the transaction to be processed // Assert that the order was cancelled successfully await expect( - getOrderStatus(orderHash, arkProvider).then((res) => + getOrderStatus(orderHash, network, arkProvider).then((res) => shortString.decodeShortString(res.orderStatus) ) ).to.eventually.equal("CANCELLED_USER"); diff --git a/packages/core/tests/cancelOffer.test.ts b/packages/core/tests/cancelOffer.test.ts index b9447223a..19de883d6 100644 --- a/packages/core/tests/cancelOffer.test.ts +++ b/packages/core/tests/cancelOffer.test.ts @@ -8,7 +8,8 @@ import { createOffer, getOrderStatus, getOrderType, - ListingV1 + ListingV1, + Network } from "../src"; import { generateRandomTokenId, @@ -30,6 +31,8 @@ describe("ArkProject cancel offer", () => { nodeUrl: "http://0.0.0.0:7777" }); + const network = "dev" as Network; + // Create a new account using the provider const { account: arkAccount } = await createAccount(arkProvider); const { account: starknetAccount } = await createAccount(starknetProvider); @@ -45,6 +48,7 @@ describe("ArkProject cancel offer", () => { // Create the listing on the blockchain using the order details let orderHash = await createOffer( + network, arkProvider, starknetAccount, arkAccount, @@ -55,14 +59,14 @@ describe("ArkProject cancel offer", () => { // Assert that the order is open await expect( - getOrderStatus(orderHash, arkProvider).then((res) => + getOrderStatus(orderHash, network, arkProvider).then((res) => shortString.decodeShortString(res.orderStatus) ) ).to.eventually.equal("OPEN"); // Assert that the order type is 'OFFER' await expect( - getOrderType(orderHash, arkProvider).then((res) => + getOrderType(orderHash, network, arkProvider).then((res) => getTypeFromCairoCustomEnum(res.orderType) ) ).to.eventually.equal("OFFER"); @@ -75,11 +79,17 @@ describe("ArkProject cancel offer", () => { }; // Cancel the order - await cancelOrder(arkProvider, starknetAccount, arkAccount, cancelInfo); + await cancelOrder( + network, + arkProvider, + starknetAccount, + arkAccount, + cancelInfo + ); // Assert that the order was cancelled successfully await expect( - getOrderStatus(orderHash, arkProvider).then((res) => + getOrderStatus(orderHash, network, arkProvider).then((res) => shortString.decodeShortString(res.orderStatus) ) ).to.eventually.equal("CANCELLED_USER"); diff --git a/packages/core/tests/fulfillListing.test.ts b/packages/core/tests/fulfillListing.test.ts index 514e7bd08..09011e5ee 100644 --- a/packages/core/tests/fulfillListing.test.ts +++ b/packages/core/tests/fulfillListing.test.ts @@ -2,6 +2,7 @@ import chai, { expect } from "chai"; import chaiAsPromised from "chai-as-promised"; import { RpcProvider, shortString } from "starknet"; +import { Network } from "../src"; import { createAccount } from "../src/actions/account/account"; import { createListing, fulfillListing } from "../src/actions/order"; import { getOrderHash, getOrderStatus } from "../src/actions/read"; @@ -22,6 +23,8 @@ describe("ArkProject Listing", () => { nodeUrl: "http://0.0.0.0:7777" }); + const network = "dev" as Network; + // Create a new account using the provider const { account: arkAccount } = await createAccount(arkProvider); const { account: starknetAccount } = await createAccount(starknetProvider); @@ -34,15 +37,22 @@ describe("ArkProject Listing", () => { startAmount: 600000000000000000 // The starting amount for the order }; - await createListing(arkProvider, starknetAccount, arkAccount, order); + await createListing( + network, + arkProvider, + starknetAccount, + arkAccount, + order + ); await sleep(2000); const { orderHash } = await getOrderHash( order.tokenId, order.tokenAddress, + network, arkProvider ); await expect( - getOrderStatus(orderHash, arkProvider).then((res) => + getOrderStatus(orderHash, network, arkProvider).then((res) => shortString.decodeShortString(res.orderStatus) ) ).to.eventually.equal("OPEN"); @@ -51,22 +61,23 @@ describe("ArkProject Listing", () => { const { account: starknetFulfillerAccount } = await createAccount(starknetProvider); - const fulfill_info = { + const fulfillInfo = { order_hash: orderHash, token_address: order.tokenAddress, token_id: order.tokenId }; fulfillListing( + network, arkProvider, starknetFulfillerAccount, arkAccount, - fulfill_info + fulfillInfo ); await sleep(1000); await expect( - getOrderStatus(orderHash, arkProvider).then((res) => + getOrderStatus(orderHash, network, arkProvider).then((res) => shortString.decodeShortString(res.orderStatus) ) ).to.eventually.equal("FULFILLED"); diff --git a/packages/core/tests/fulfillOffer.test.ts b/packages/core/tests/fulfillOffer.test.ts index 0ca51e758..c10b30cfc 100644 --- a/packages/core/tests/fulfillOffer.test.ts +++ b/packages/core/tests/fulfillOffer.test.ts @@ -7,6 +7,7 @@ import { createOffer, fulfillOffer, getOrderStatus, + Network, OfferV1 } from "../src"; import { generateRandomTokenId } from "./utils"; @@ -27,6 +28,8 @@ describe("ArkProject Listing and Offer Fulfillment", () => { nodeUrl: "http://0.0.0.0:7777" }); + const network = "dev" as Network; + // Create a new account for the listing using the provider const { account: arkAccount } = await createAccount(arkProvider); const { account: starknetAccount } = await createAccount(starknetProvider); @@ -42,6 +45,7 @@ describe("ArkProject Listing and Offer Fulfillment", () => { // Create the listing on the arkchain using the order details const orderHash = await createOffer( + network, arkProvider, starknetAccount, arkAccount, @@ -53,6 +57,7 @@ describe("ArkProject Listing and Offer Fulfillment", () => { let { orderStatus: orderStatusBefore } = await getOrderStatus( orderHash, + network, arkProvider ); expect(shortString.decodeShortString(orderStatusBefore)).to.equal("OPEN"); @@ -72,6 +77,7 @@ describe("ArkProject Listing and Offer Fulfillment", () => { // Fulfill the offer await fulfillOffer( + network, arkProvider, starknetFulfillerAccount, arkAccount, @@ -82,6 +88,7 @@ describe("ArkProject Listing and Offer Fulfillment", () => { let { orderStatus: orderStatusAfter } = await getOrderStatus( orderHash, + network, arkProvider ); diff --git a/packages/deployer/package.json b/packages/deployer/package.json index 8fa43249e..788f0d616 100644 --- a/packages/deployer/package.json +++ b/packages/deployer/package.json @@ -11,7 +11,7 @@ "deploy:solis": "npm run build && node ./dist/deployArkchainContracts.js", "deploy:starknet:tokens": "npm run build && node ./dist/deployStarknetFreemintNft.js", "deploy:starknet": "npm run build && node ./dist/deployStarknetContracts.js", - "deploy:starknet:all": "pnpm run deploy:clean && pnpm run deploy:starknet && pnpm run deploy:starknet:tokens", + "deploy:starknet:all": "npm run build && node ./dist/redeployStarknetContracts.js", "deploy:clean": "npm run build && node ./dist/cleanContracts.js" }, "keywords": [], diff --git a/packages/deployer/src/accounts/deploy.ts b/packages/deployer/src/accounts/deploy.ts index b1846f52c..d263889fe 100644 --- a/packages/deployer/src/accounts/deploy.ts +++ b/packages/deployer/src/accounts/deploy.ts @@ -2,18 +2,18 @@ import { promises as fs } from "fs"; import { join } from "path"; import { Command } from "commander"; -import { Account, CallData, RpcProvider } from "starknet"; +import { Account, CallData } from "starknet"; -import "dotenv/config"; - -import { SOLIS_NETWORK, STARKNET_NETWORK } from "../constants"; -import { getProvider } from "../providers"; +import { getStarknetProvider } from "../providers"; import { OZaccountClassHash } from "./constants"; -async function deployAccount(network: string) { - const { starknetProvider } = getProvider(STARKNET_NETWORK, SOLIS_NETWORK); +async function deployAccount(starknetNetwork: string) { + const starknetProvider = getStarknetProvider(starknetNetwork); - const accountsFilePath = join(__dirname, `../../accounts/${network}.json`); + const accountsFilePath = join( + __dirname, + `../../accounts/${starknetNetwork}.json` + ); let accounts: any[] = []; try { const fileData = await fs.readFile(accountsFilePath, "utf8"); @@ -60,11 +60,11 @@ async function deployAccount(network: string) { } const program = new Command(); -program.option("-n, --network ", "Network to use", "goerli"); +program.option("-n", "Starknet Network to use", "dev"); program.parse(process.argv); const options = program.opts(); -const network = options.network; +const { starknet } = options; -deployAccount(network).catch(console.error); +deployAccount(starknet).catch(console.error); diff --git a/packages/deployer/src/accounts/new.ts b/packages/deployer/src/accounts/new.ts index 24f12dbfb..094b94acb 100644 --- a/packages/deployer/src/accounts/new.ts +++ b/packages/deployer/src/accounts/new.ts @@ -59,7 +59,7 @@ export async function createNewAccounts( const program = new Command(); program - .option("-n, --network ", "Network to use", "goerli") + .option("-n, --network ", "Network to use", "dev") .option("-a, --accounts ", "Number of accounts to create", "1"); program.parse(process.argv); diff --git a/packages/deployer/src/cleanContracts.ts b/packages/deployer/src/cleanContracts.ts index 601678660..af8ceffc5 100644 --- a/packages/deployer/src/cleanContracts.ts +++ b/packages/deployer/src/cleanContracts.ts @@ -1,15 +1,3 @@ -import { promises as fs } from "fs"; +import { cleanContracts } from "./utils"; -import { getContractsFilePath } from "./utils"; - -(async () => { - await fs.writeFile( - getContractsFilePath(), - JSON.stringify({ - goerli: {}, - sepolia: {}, - mainnet: {}, - local: {} - }) - ); -})(); +cleanContracts(); diff --git a/packages/deployer/src/constants.ts b/packages/deployer/src/constants.ts deleted file mode 100644 index 640bb3485..000000000 --- a/packages/deployer/src/constants.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ProviderNetwork } from "./types"; - -export const STARKNET_NETWORK = (process.env.STARKNET_NETWORK_ID || - "local") as ProviderNetwork; -export const SOLIS_NETWORK = (process.env.SOLIS_NETWORK_ID || - "local") as ProviderNetwork; diff --git a/packages/deployer/src/deployArkchainContracts.ts b/packages/deployer/src/deployArkchainContracts.ts index d32fb15df..27b30738b 100644 --- a/packages/deployer/src/deployArkchainContracts.ts +++ b/packages/deployer/src/deployArkchainContracts.ts @@ -1,21 +1,30 @@ import { promises as fs } from "fs"; +import { program } from "commander"; import loading from "loading-cli"; -import { SOLIS_NETWORK, STARKNET_NETWORK } from "./constants"; import { updateOrderbookAddress } from "./contracts/executor"; import { deployOrderBook, updateExecutorAddress } from "./contracts/orderbook"; -import { getProvider } from "./providers"; +import { getSolisProvider, getStarknetProvider } from "./providers"; import { getContractsFilePath, - getExistingAccounts, - getExistingContracts + getExistingContracts, + getExistingSolisAccounts, + getExistingStarknetAccounts } from "./utils"; import "dotenv/config"; const artifactsPath = "../../contracts/target/dev/"; +program.option("-sn, --starknet ", "Starknet Network", "dev"); +program.option("-so, --solis ", "Solis Network", "dev"); +program.parse(); + +const options = program.opts(); +const starknetNetwork = options.starknet; +const solisNetwork = options.solis; + async function setSolisAddresses( orderbookAddress: string, executorAddress: string @@ -53,16 +62,12 @@ async function setSolisAddresses( } } -async function deployArkchainContracts() { - const { solisProvider, starknetProvider } = getProvider( - STARKNET_NETWORK, - SOLIS_NETWORK - ); - - const { starknetAccounts, arkchainAccounts } = getExistingAccounts( - STARKNET_NETWORK, - SOLIS_NETWORK - ); +async function deployArkchainContracts( + solisNetwork: string, + starknetNetwork: string +) { + const solisProvider = getSolisProvider(solisNetwork); + const arkchainAccounts = getExistingSolisAccounts(solisNetwork); const arkchainAdminAccount = arkchainAccounts[0]; @@ -74,8 +79,6 @@ async function deployArkchainContracts() { console.log("\n"); - const existingContracts = await getExistingContracts(); - const arkchainSpinner = loading("💠 Deploying Arkchain Contracts...").start(); if (arkchainAdminAccount) { @@ -87,11 +90,11 @@ async function deployArkchainContracts() { ); const fileContent = await fs.readFile(getContractsFilePath(), "utf8"); const contracts = JSON.parse(fileContent); - const { executor: executorAddress } = contracts[STARKNET_NETWORK]; + const { executor: executorAddress } = contracts[starknetNetwork]; arkchainSpinner.text = "💠 Updating executor address..."; const existingContracts = await getExistingContracts(); - existingContracts[SOLIS_NETWORK].orderbook = orderbookContract.address; + existingContracts[solisNetwork].orderbook = orderbookContract.address; await fs.writeFile( getContractsFilePath(), JSON.stringify(existingContracts) @@ -106,7 +109,10 @@ async function deployArkchainContracts() { arkchainSpinner.text = "💠 Updating Executor Contract on Starknet..."; + const starknetProvider = getStarknetProvider(starknetNetwork); + const starknetAccounts = getExistingStarknetAccounts(starknetNetwork); const adminAccount = starknetAccounts[0]; + if (adminAccount) { await updateOrderbookAddress( starknetProvider, @@ -125,4 +131,4 @@ async function deployArkchainContracts() { } } -deployArkchainContracts(); +deployArkchainContracts(solisNetwork, starknetNetwork); diff --git a/packages/deployer/src/deployStarknetContracts.ts b/packages/deployer/src/deployStarknetContracts.ts index e16ef9b2e..8d4ecf38d 100644 --- a/packages/deployer/src/deployStarknetContracts.ts +++ b/packages/deployer/src/deployStarknetContracts.ts @@ -1,127 +1,12 @@ -import { promises as fs } from "fs"; -import { join } from "path"; +import { program } from "commander"; -import * as sn from "starknet"; - -import { SOLIS_NETWORK, STARKNET_NETWORK } from "./constants"; -import { deployExecutor, upgradeExecutor } from "./contracts/executor"; -import { deployMessaging, upgradeMessaging } from "./contracts/messaging"; -import { getFeeAddress, getProvider } from "./providers"; -import { ProviderNetwork } from "./types"; -import { - getContractsFilePath, - getExistingAccounts, - getExistingContracts -} from "./utils"; +import { deployStarknetContracts } from "./utils"; const artifactsPath = "../../contracts/target/dev/"; -const loading = require("loading-cli"); - -function getMessagingFilePath(network: ProviderNetwork): string { - switch (network) { - case "mainnet": - return join(__dirname, "../../../crates/solis/messaging.json"); - case "goerli": - return join(__dirname, "../../../crates/solis/messaging.goerli.json"); - case "sepolia": - return join(__dirname, "../../../crates/solis/messaging.goerli.json"); - case "local": - return join(__dirname, "../../../crates/solis/messaging.local.json"); - default: - return join(__dirname, "../../../crates/solis/messaging.local.json"); - } -} - -async function deployStarknetContracts() { - const { starknetProvider } = getProvider(STARKNET_NETWORK, SOLIS_NETWORK); - const { starknetAccounts } = getExistingAccounts( - STARKNET_NETWORK, - SOLIS_NETWORK - ); - - const [starknetAdminAccount, ...otherUsers] = starknetAccounts; - - const existingContracts = await getExistingContracts(); - console.log("\nSTARKNET ACCOUNTS"); - console.log("=================\n"); - console.log(`| Admin account | ${starknetAdminAccount.address}`); - if (otherUsers.length > 0) { - otherUsers.forEach((user, index) => { - console.log(`| User ${index} | ${user.address}`); - }); - } - - console.log(""); - - const starknetSpinner = loading("💅 Deploying Starknet Contracts...").start(); - - let messagingContract: sn.Contract; - if ( - existingContracts[STARKNET_NETWORK].messaging && - !STARKNET_NETWORK.includes("local") - ) { - starknetSpinner.text = "Upgrading Messaging Contract..."; - messagingContract = await upgradeMessaging( - artifactsPath, - starknetAdminAccount, - starknetProvider, - existingContracts[STARKNET_NETWORK].messaging - ); - } else { - starknetSpinner.text = "Deploying Messaging Contract..."; - messagingContract = await deployMessaging( - artifactsPath, - starknetAdminAccount, - starknetProvider - ); - existingContracts[STARKNET_NETWORK].messaging = messagingContract.address; - await fs.writeFile( - getContractsFilePath(), - JSON.stringify(existingContracts) - ); - } - - starknetSpinner.text = "⚡ Deploying Executor Contract..."; - let executorContract: sn.Contract; - if ( - existingContracts[STARKNET_NETWORK].executor && - !STARKNET_NETWORK.includes("local") - ) { - starknetSpinner.text = "⚡ Upgrading Executor Contract..."; - executorContract = await upgradeExecutor( - artifactsPath, - starknetAdminAccount, - starknetProvider, - existingContracts[STARKNET_NETWORK].messaging - ); - } else { - starknetSpinner.text = "⚡ Deploying Executor Contract..."; - executorContract = await deployExecutor( - artifactsPath, - starknetAdminAccount, - starknetProvider, - getFeeAddress(STARKNET_NETWORK), - messagingContract.address - ); - existingContracts[STARKNET_NETWORK].executor = executorContract.address; - await fs.writeFile( - getContractsFilePath(), - JSON.stringify(existingContracts) - ); - - const messagingFilePath = getMessagingFilePath(STARKNET_NETWORK); - const configData = JSON.parse(await fs.readFile(messagingFilePath, "utf8")); - configData.contract_address = messagingContract.address; - await fs.writeFile(messagingFilePath, JSON.stringify(configData, null, 2)); - } - - starknetSpinner.stop(); - - console.log("STARKNET CONTRACTS"); - console.log("==================\n"); - console.log(`| Messaging contract | ${messagingContract.address}`); - console.log(`| Executor contract | ${executorContract.address}`); -} +program.option("-n, --network ", "Starknet Network", "dev"); +program.parse(); +const options = program.opts(); +const network = options.network; -deployStarknetContracts(); +deployStarknetContracts(network, artifactsPath); diff --git a/packages/deployer/src/deployStarknetFreemintNft.ts b/packages/deployer/src/deployStarknetFreemintNft.ts index 821f5f04e..10b46b1a3 100644 --- a/packages/deployer/src/deployStarknetFreemintNft.ts +++ b/packages/deployer/src/deployStarknetFreemintNft.ts @@ -1,103 +1,11 @@ -import { promises as fs } from "fs"; +import { program } from "commander"; -import { Account, CallData, Contract, RpcProvider } from "starknet"; +import { deployFreemintContracts } from "./utils"; -import { SOLIS_NETWORK, STARKNET_NETWORK } from "./constants"; -import { loadArtifacts } from "./contracts/common"; -import { deployERC20 } from "./contracts/erc20"; -import { getProvider } from "./providers"; -import { - getContractsFilePath, - getExistingAccounts, - getExistingContracts -} from "./utils"; - -const loading = require("loading-cli"); const artifactsPath = "../../contracts/target/dev/"; +program.option("-n, --network ", "Starknet Network", "dev"); +program.parse(); +const options = program.opts(); +const { network } = options; -export async function deployStarknetContracts() { - const { starknetProvider } = getProvider(STARKNET_NETWORK, SOLIS_NETWORK); - const { starknetAccounts } = getExistingAccounts( - STARKNET_NETWORK, - SOLIS_NETWORK - ); - const [starknetAdminAccount, ...otherUsers] = starknetAccounts; - - let existingContracts = await getExistingContracts(); - - console.log("\nSTARKNET ACCOUNTS"); - console.log("=================\n"); - console.log(`| Admin account | ${starknetAdminAccount.address}`); - if (otherUsers.length > 0) { - otherUsers.forEach((user, index) => { - console.log(`| User ${index} | ${user.address}`); - }); - } - - console.log(""); - - const starknetSpinner = loading("Deploying Nft Contract...").start(); - const artifacts = loadArtifacts(artifactsPath, "ark_tokens_FreeMintNFT"); - - const contractCallData = new CallData(artifacts.sierra.abi); - const contractConstructor = contractCallData.compile("constructor", { - name: "ARK", - symbol: "ARK" - }); - - const deployR = await starknetAdminAccount.declareAndDeploy({ - contract: artifacts.sierra, - casm: artifacts.casm, - constructorCalldata: contractConstructor - }); - - const nftContract = new Contract( - artifacts.sierra.abi, - deployR.deploy.contract_address, - starknetProvider - ); - - existingContracts = { - ...existingContracts, - [STARKNET_NETWORK]: { - ...existingContracts[STARKNET_NETWORK], - nftContract: nftContract.address - } - }; - - await fs.writeFile(getContractsFilePath(), JSON.stringify(existingContracts)); - - let ethContract: Contract | undefined; - if (STARKNET_NETWORK === "local") { - starknetSpinner.text = "Deploying Eth Contract..."; - - ethContract = await deployERC20( - artifactsPath, - starknetAdminAccount, - starknetProvider, - "ETH", - "ETH" - ); - - existingContracts = { - ...existingContracts, - [STARKNET_NETWORK]: { - ...existingContracts[STARKNET_NETWORK], - eth: ethContract.address - } - }; - - await fs.writeFile( - getContractsFilePath(), - JSON.stringify(existingContracts) - ); - } - - starknetSpinner.stop(); - console.log("- Nft contract: ", nftContract.address); - if (ethContract) { - console.log("- Eth contract: ", ethContract.address); - } -} - -deployStarknetContracts(); +deployFreemintContracts(network, artifactsPath); diff --git a/packages/deployer/src/providers.ts b/packages/deployer/src/providers.ts index 8ec9ea9ff..b61363097 100644 --- a/packages/deployer/src/providers.ts +++ b/packages/deployer/src/providers.ts @@ -1,45 +1,47 @@ import { RpcProvider } from "starknet"; -export function getProvider(solisNetwork: string, starknetNetwork: string) { - let solisNodeUrl: string; +export function getStarknetProvider(starknetNetwork: string) { let starknetNodeUrl: string; - - switch (solisNetwork) { - case "local": - solisNodeUrl = "http://0.0.0.0:7777"; + switch (starknetNetwork) { + case "dev": + starknetNodeUrl = "http://0.0.0.0:5050"; break; case "mainnet": - solisNodeUrl = - process.env.MAINNET_SOLIS_NODE_URL ?? "default_mainnet_solis_url"; // Replace with default or throw error if not set + starknetNodeUrl = + process.env.MAINNET_STARKNET_NODE_URL ?? "default_mainnet_starknet_url"; // Replace with default or throw error if not set break; case "testnet": - solisNodeUrl = - process.env.TESTNET_SOLIS_NODE_URL ?? "default_testnet_solis_url"; // Replace with default or throw error if not set + starknetNodeUrl = + process.env.TESTNET_STARKNET_NODE_URL ?? "default_testnet_starknet_url"; break; default: - throw new Error(`Unsupported solisNetwork: ${solisNetwork}`); + throw new Error(`Unsupported starknetNetwork: ${starknetNetwork}`); } + const starknetProvider = new RpcProvider({ nodeUrl: starknetNodeUrl }); + return starknetProvider; +} - switch (starknetNetwork) { - case "local": - starknetNodeUrl = "http://0.0.0.0:5050"; +export function getSolisProvider(solisNetwork: string) { + let solisNodeUrl: string; + + switch (solisNetwork) { + case "dev": + solisNodeUrl = "http://0.0.0.0:7777"; break; case "mainnet": - starknetNodeUrl = - process.env.MAINNET_STARKNET_NODE_URL ?? "default_mainnet_starknet_url"; // Replace with default or throw error if not set + solisNodeUrl = + process.env.MAINNET_SOLIS_NODE_URL ?? "default_mainnet_solis_url"; // Replace with default or throw error if not set break; case "testnet": - starknetNodeUrl = - process.env.TESTNET_STARKNET_NODE_URL ?? "default_testnet_starknet_url"; // Replace with default or throw error if not set + solisNodeUrl = + process.env.TESTNET_SOLIS_NODE_URL ?? "default_testnet_solis_url"; // Replace with default or throw error if not set break; default: - throw new Error(`Unsupported starknetNetwork: ${starknetNetwork}`); + throw new Error(`Unsupported solisNetwork: ${solisNetwork}`); } const solisProvider = new RpcProvider({ nodeUrl: solisNodeUrl }); - const starknetProvider = new RpcProvider({ nodeUrl: starknetNodeUrl }); - - return { solisProvider, starknetProvider }; + return solisProvider; } export function getFeeAddress(network: string) { diff --git a/packages/deployer/src/redeployStarknetContracts.ts b/packages/deployer/src/redeployStarknetContracts.ts new file mode 100644 index 000000000..52315c3bb --- /dev/null +++ b/packages/deployer/src/redeployStarknetContracts.ts @@ -0,0 +1,19 @@ +import { program } from "commander"; + +import { + cleanContracts, + deployFreemintContracts, + deployStarknetContracts +} from "./utils"; + +program.option("-n, --network ", "Starknet Network", "dev"); +program.parse(); +const options = program.opts(); +const { network } = options; + +(async (network: string) => { + const artifactsPath = "../../contracts/target/dev/"; + await cleanContracts(); + await deployFreemintContracts(network, artifactsPath); + await deployStarknetContracts(network, artifactsPath); +})(network); diff --git a/packages/deployer/src/types.ts b/packages/deployer/src/types.ts index 7afef46c2..a4cb18242 100644 --- a/packages/deployer/src/types.ts +++ b/packages/deployer/src/types.ts @@ -1 +1 @@ -export type ProviderNetwork = "mainnet" | "goerli" | "sepolia" | "local"; +export type ProviderNetwork = "mainnet" | "testnet" | "dev"; diff --git a/packages/deployer/src/utils.ts b/packages/deployer/src/utils.ts index df34fdb21..b2a9a4267 100644 --- a/packages/deployer/src/utils.ts +++ b/packages/deployer/src/utils.ts @@ -1,78 +1,82 @@ import { promises as fs } from "fs"; import { join } from "path"; -import { Account, RpcProvider } from "starknet"; +import loading from "loading-cli"; +import { Account, CallData, Contract, RpcProvider } from "starknet"; -import { getProvider } from "./providers"; -import { ProviderNetwork } from "./types"; +import { loadArtifacts } from "./contracts/common"; +import { deployERC20 } from "./contracts/erc20"; +import { deployExecutor, upgradeExecutor } from "./contracts/executor"; +import { deployMessaging, upgradeMessaging } from "./contracts/messaging"; +import { + getFeeAddress, + getSolisProvider, + getStarknetProvider +} from "./providers"; -export function getExistingAccounts( - starknetNetwork: ProviderNetwork, - solisNetwork: ProviderNetwork -) { - const { solisProvider, starknetProvider } = getProvider( - starknetNetwork, - solisNetwork - ); - - const starknetAccounts = [ +export function getExistingSolisAccounts(solisNetwork: string) { + const solisProvider = getSolisProvider(solisNetwork); + const solisAccounts = [ { address: - process.env.STARKNET_ACCOUNT1_ADDRESS || + process.env.SOLIS_ACCOUNT1_ADDRESS || "0x517ececd29116499f4a1b64b094da79ba08dfd54a3edaa316134c41f8160973", privateKey: - process.env.STARKNET_ACCOUNT1_PRIVATE_KEY || + process.env.SOLIS_ACCOUNT1_PRIVATE_KEY || "0x1800000000300000180000000000030000000000003006001800006600", publicKey: - process.env.STARKNET_ACCOUNT1_PUBLIC_KEY || + process.env.SOLIS_ACCOUNT1_PUBLIC_KEY || "0x2b191c2f3ecf685a91af7cf72a43e7b90e2e41220175de5c4f7498981b10053", deployed: true }, { address: - process.env.STARKNET_ACCOUNT1_PRIVATE_KEY || + process.env.SOLIS_ACCOUNT2_ADDRESS || "0x5686a647a9cdd63ade617e0baf3b364856b813b508f03903eb58a7e622d5855", privateKey: - process.env.STARKNET_ACCOUNT1_PRIVATE_KEY || + process.env.SOLIS_ACCOUNT2_PRIVATE_KEY || "0x33003003001800009900180300d206308b0070db00121318d17b5e6262150b", publicKey: - process.env.STARKNET_ACCOUNT1_PUBLIC_KEY || + process.env.SOLIS_ACCOUNT2_PUBLIC_KEY || "0x4c0f884b8e5b4f00d97a3aad26b2e5de0c0c76a555060c837da2e287403c01d", deployed: true } ]; - const solisAccounts = [ + return buildAccounts(solisProvider, solisAccounts); +} + +export function getExistingStarknetAccounts(starknetNetwork: string) { + const starknetProvider = getStarknetProvider(starknetNetwork); + + const starknetAccounts = [ { address: - process.env.SOLIS_ACCOUNT1_ADDRESS || + process.env.STARKNET_ACCOUNT1_ADDRESS || "0x517ececd29116499f4a1b64b094da79ba08dfd54a3edaa316134c41f8160973", privateKey: - process.env.SOLIS_ACCOUNT1_PRIVATE_KEY || + process.env.STARKNET_ACCOUNT1_PRIVATE_KEY || "0x1800000000300000180000000000030000000000003006001800006600", publicKey: - process.env.SOLIS_ACCOUNT1_PUBLIC_KEY || + process.env.STARKNET_ACCOUNT1_PUBLIC_KEY || "0x2b191c2f3ecf685a91af7cf72a43e7b90e2e41220175de5c4f7498981b10053", deployed: true }, { address: - process.env.SOLIS_ACCOUNT2_ADDRESS || + process.env.STARKNET_ACCOUNT1_PRIVATE_KEY || "0x5686a647a9cdd63ade617e0baf3b364856b813b508f03903eb58a7e622d5855", privateKey: - process.env.SOLIS_ACCOUNT2_PRIVATE_KEY || + process.env.STARKNET_ACCOUNT1_PRIVATE_KEY || "0x33003003001800009900180300d206308b0070db00121318d17b5e6262150b", publicKey: - process.env.SOLIS_ACCOUNT2_PUBLIC_KEY || + process.env.STARKNET_ACCOUNT1_PUBLIC_KEY || "0x4c0f884b8e5b4f00d97a3aad26b2e5de0c0c76a555060c837da2e287403c01d", deployed: true } ]; - return { - starknetAccounts: buildAccounts(starknetProvider, starknetAccounts), - arkchainAccounts: buildAccounts(solisProvider, solisAccounts) - }; + return buildAccounts(starknetProvider, starknetAccounts); } function buildAccounts(provider: RpcProvider, accountData: any[]): Account[] { @@ -81,6 +85,18 @@ function buildAccounts(provider: RpcProvider, accountData: any[]): Account[] { }); } +function getMessagingFilePath(network: string): string { + switch (network) { + case "mainnet": + return join(__dirname, "../../../crates/solis/messaging.json"); + case "testnet": + return join(__dirname, "../../../crates/solis/messaging.goerli.json"); + case "dev": + default: + return join(__dirname, "../../../crates/solis/messaging.local.json"); + } +} + export function getContractsFilePath() { return join(__dirname, `../../../contracts.json`); } @@ -95,3 +111,185 @@ export async function getExistingContracts() { throw error; } } + +export async function deployFreemintContracts( + network: string, + artifactsPath: string +) { + const starknetProvider = getStarknetProvider(network); + const starknetAccounts = getExistingStarknetAccounts(network); + const [starknetAdminAccount, ...otherUsers] = starknetAccounts; + + let existingContracts = await getExistingContracts(); + + console.log("\nSTARKNET ACCOUNTS"); + console.log("=================\n"); + console.log(`| Admin account | ${starknetAdminAccount.address}`); + if (otherUsers.length > 0) { + otherUsers.forEach((user, index) => { + console.log(`| User ${index} | ${user.address}`); + }); + } + + console.log(""); + + const starknetSpinner = loading("Deploying Nft Contract...").start(); + const artifacts = loadArtifacts(artifactsPath, "ark_tokens_FreeMintNFT"); + + const contractCallData = new CallData(artifacts.sierra.abi); + const contractConstructor = contractCallData.compile("constructor", { + name: "ARK", + symbol: "ARK" + }); + + const deployR = await starknetAdminAccount.declareAndDeploy({ + contract: artifacts.sierra, + casm: artifacts.casm, + constructorCalldata: contractConstructor + }); + + const nftContract = new Contract( + artifacts.sierra.abi, + deployR.deploy.contract_address, + starknetProvider + ); + + existingContracts = { + ...existingContracts, + [network]: { + ...existingContracts[network], + nftContract: nftContract.address + } + }; + + await fs.writeFile(getContractsFilePath(), JSON.stringify(existingContracts)); + + let ethContract: Contract | undefined; + if (network === "dev") { + starknetSpinner.text = "Deploying Eth Contract..."; + + ethContract = await deployERC20( + artifactsPath, + starknetAdminAccount, + starknetProvider, + "ETH", + "ETH" + ); + + existingContracts = { + ...existingContracts, + [network]: { + ...existingContracts[network], + eth: ethContract.address + } + }; + + await fs.writeFile( + getContractsFilePath(), + JSON.stringify(existingContracts) + ); + } + + starknetSpinner.stop(); + console.log("- Nft contract: ", nftContract.address); + if (ethContract) { + console.log("- Eth contract: ", ethContract.address); + } +} + +export async function deployStarknetContracts( + network: string, + artifactsPath: string +) { + const messagingFilePath = getMessagingFilePath(network); + const starknetProvider = getStarknetProvider(network); + const starknetAccounts = getExistingStarknetAccounts(network); + + const [starknetAdminAccount, ...otherUsers] = starknetAccounts; + + const existingContracts = await getExistingContracts(); + console.log("\nSTARKNET ACCOUNTS"); + console.log("=================\n"); + console.log(`| Admin account | ${starknetAdminAccount.address}`); + if (otherUsers.length > 0) { + otherUsers.forEach((user, index) => { + console.log(`| User ${index} | ${user.address}`); + }); + } + + console.log(""); + + const starknetSpinner = loading("💅 Deploying Starknet Contracts...").start(); + + let messagingContract: Contract; + if (existingContracts[network].messaging && !network.includes("dev")) { + starknetSpinner.text = "Upgrading Messaging Contract..."; + messagingContract = await upgradeMessaging( + artifactsPath, + starknetAdminAccount, + starknetProvider, + existingContracts[network].messaging + ); + } else { + starknetSpinner.text = "Deploying Messaging Contract..."; + messagingContract = await deployMessaging( + artifactsPath, + starknetAdminAccount, + starknetProvider + ); + existingContracts[network].messaging = messagingContract.address; + await fs.writeFile( + getContractsFilePath(), + JSON.stringify(existingContracts) + ); + } + + starknetSpinner.text = "⚡ Deploying Executor Contract..."; + let executorContract: Contract; + if (existingContracts[network].executor && !network.includes("dev")) { + starknetSpinner.text = "⚡ Upgrading Executor Contract..."; + executorContract = await upgradeExecutor( + artifactsPath, + starknetAdminAccount, + starknetProvider, + existingContracts[network].messaging + ); + } else { + starknetSpinner.text = "⚡ Deploying Executor Contract..."; + executorContract = await deployExecutor( + artifactsPath, + starknetAdminAccount, + starknetProvider, + getFeeAddress(network), + messagingContract.address + ); + existingContracts[network].executor = executorContract.address; + await fs.writeFile( + getContractsFilePath(), + JSON.stringify(existingContracts) + ); + + const messagingFilePath = getMessagingFilePath(network); + const configData = JSON.parse(await fs.readFile(messagingFilePath, "utf8")); + configData.contract_address = messagingContract.address; + await fs.writeFile(messagingFilePath, JSON.stringify(configData, null, 2)); + } + + starknetSpinner.stop(); + + console.log("STARKNET CONTRACTS"); + console.log("==================\n"); + console.log(`| Messaging contract | ${messagingContract.address}`); + console.log(`| Executor contract | ${executorContract.address}`); +} + +export async function cleanContracts() { + await fs.writeFile( + getContractsFilePath(), + JSON.stringify({ + testnet: {}, + mainnet: {}, + dev: {} + }) + ); +} diff --git a/packages/example/src/app/page.tsx b/packages/example/src/app/page.tsx index 95bae09ae..d8505944b 100644 --- a/packages/example/src/app/page.tsx +++ b/packages/example/src/app/page.tsx @@ -2,7 +2,7 @@ import { useAccount } from "@starknet-react/core"; -import { ArkProvider, Network } from "@ark-project/react"; +import { ArkProvider, type Network } from "@ark-project/react"; import { MainNav } from "@/components/main-nav"; import { UserNav } from "@/components/user-nav"; @@ -15,7 +15,7 @@ export default function Home() { if (account === undefined) return ; return ( <> - +
diff --git a/packages/react/components/ArkProvider/RpcContext.tsx b/packages/react/components/ArkProvider/RpcContext.tsx index 73678d135..b6c2f7508 100644 --- a/packages/react/components/ArkProvider/RpcContext.tsx +++ b/packages/react/components/ArkProvider/RpcContext.tsx @@ -10,23 +10,18 @@ import React, { import { RpcProvider } from "starknet"; -import { createAccount } from "@ark-project/core"; - -export enum Network { - Mainnet, - Testnet, - Dev -} +import { createAccount, Network } from "@ark-project/core"; const NETWORK_TO_RPC_NODE_URL: Record = { - [Network.Mainnet]: "https://solis.arkproject.dev", - [Network.Testnet]: "https://staging.solis.arkproject.dev", - [Network.Dev]: "http://localhost:7777" + mainnet: "https://solis.arkproject.dev", + testnet: "https://staging.solis.arkproject.dev", + dev: "http://localhost:7777" }; type RpcContextValue = | { rpcProvider: RpcProvider; + network: Network; } | undefined; @@ -45,7 +40,8 @@ export function RpcProviderProvider( () => ({ rpcProvider: new RpcProvider({ nodeUrl: NETWORK_TO_RPC_NODE_URL[network] - }) + }), + network }), [network] ); @@ -82,7 +78,7 @@ export function useRpc() { throw new Error("useRpc must be used within an ArkProvider"); } - const { rpcProvider } = rpcContext; + const { rpcProvider, network } = rpcContext; - return { rpcProvider }; + return { rpcProvider, network }; } diff --git a/packages/react/components/index.ts b/packages/react/components/index.ts index 6c1181c98..b143b34d1 100644 --- a/packages/react/components/index.ts +++ b/packages/react/components/index.ts @@ -1,2 +1 @@ export { ArkProvider } from "./ArkProvider/ArkProvider"; -export { Network } from "./ArkProvider/RpcContext"; diff --git a/packages/react/hooks/useCreateListing.ts b/packages/react/hooks/useCreateListing.ts index ddefe57c9..74d6272c1 100644 --- a/packages/react/hooks/useCreateListing.ts +++ b/packages/react/hooks/useCreateListing.ts @@ -1,9 +1,12 @@ import { useState } from "react"; +import { useProvider } from "@starknet-react/core"; import { Account, AccountInterface } from "starknet"; import { + approveERC721, createListing as createListingCore, + getContractAddresses, ListingV1 } from "@ark-project/core"; @@ -12,10 +15,14 @@ import { Status } from "../types/hooks"; import { useOwner } from "./useOwner"; export default function useCreateListing() { - const { rpcProvider } = useRpc(); + const { rpcProvider, network } = useRpc(); const [status, setStatus] = useState("idle"); const [response, setResponse] = useState(undefined); const owner = useOwner(); + const { STARKNET_EXECUTOR_ADDRESS } = getContractAddresses(network); + + const starknetProvider = useProvider(); + async function createListing( starknetAccount: AccountInterface, order: ListingV1 @@ -23,6 +30,7 @@ export default function useCreateListing() { const burner_address = localStorage.getItem("burner_address"); const burner_private_key = localStorage.getItem("burner_private_key"); const burner_public_key = localStorage.getItem("burner_public_key"); + if ( burner_address === null || burner_private_key === null || @@ -33,7 +41,17 @@ export default function useCreateListing() { try { setStatus("loading"); + + await approveERC721( + starknetProvider.provider, + starknetAccount, + order.tokenAddress.toString(), + STARKNET_EXECUTOR_ADDRESS, + order.tokenId + ); + const orderHash = await createListingCore( + network, rpcProvider, starknetAccount, new Account(rpcProvider, burner_address, burner_private_key), diff --git a/packages/react/hooks/useCreateOffer.ts b/packages/react/hooks/useCreateOffer.ts index c01cadd00..4db1b5d79 100644 --- a/packages/react/hooks/useCreateOffer.ts +++ b/packages/react/hooks/useCreateOffer.ts @@ -9,7 +9,7 @@ import { Status } from "../types/hooks"; import { useOwner } from "./useOwner"; export default function useCreateOffer() { - const { rpcProvider } = useRpc(); + const { rpcProvider, network } = useRpc(); const [status, setStatus] = useState("idle"); const [response, setResponse] = useState(undefined); const owner = useOwner(); @@ -33,6 +33,7 @@ export default function useCreateOffer() { try { setStatus("loading"); const orderHash = await createOfferCore( + network, rpcProvider, starknetAccount, new Account(rpcProvider, burner_address, burner_private_key), diff --git a/packages/react/hooks/useFulfillListing.ts b/packages/react/hooks/useFulfillListing.ts index 8c385ca11..c6ebc1b8a 100644 --- a/packages/react/hooks/useFulfillListing.ts +++ b/packages/react/hooks/useFulfillListing.ts @@ -10,7 +10,7 @@ import { Status } from "../types/hooks"; import { useOwner } from "./useOwner"; export default function useFulfillListing() { - const { rpcProvider } = useRpc(); + const { rpcProvider, network } = useRpc(); const [status, setStatus] = useState("idle"); const owner = useOwner(); async function fulfillListing( @@ -31,6 +31,7 @@ export default function useFulfillListing() { try { setStatus("loading"); await fulfillListingCore( + network, rpcProvider, starknetAccount, new Account(rpcProvider, burner_address, burner_private_key), diff --git a/packages/react/hooks/useFulfillOffer.ts b/packages/react/hooks/useFulfillOffer.ts index 2670630ce..4570d71d1 100644 --- a/packages/react/hooks/useFulfillOffer.ts +++ b/packages/react/hooks/useFulfillOffer.ts @@ -10,9 +10,10 @@ import { Status } from "../types/hooks"; import { useOwner } from "./useOwner"; export default function useFulfillOffer() { - const { rpcProvider } = useRpc(); + const { rpcProvider, network } = useRpc(); const [status, setStatus] = useState("idle"); const owner = useOwner(); + async function fulfillOffer( starknetAccount: AccountInterface, fulfillOfferInfo: FulfillOfferInfo @@ -31,6 +32,7 @@ export default function useFulfillOffer() { try { setStatus("loading"); await fulfillOfferCore( + network, rpcProvider, starknetAccount, new Account(rpcProvider, burner_address, burner_private_key), diff --git a/packages/react/index.tsx b/packages/react/index.tsx index a234113be..47b73edad 100644 --- a/packages/react/index.tsx +++ b/packages/react/index.tsx @@ -1,2 +1,4 @@ +export type { Network } from "@ark-project/core"; + export * from "./components"; export * from "./hooks";