Skip to content

Commit

Permalink
Integrated Access List factory. Created tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
mariacarmina committed Sep 4, 2024
1 parent 47500b0 commit 9695585
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/@types/NFTFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,12 @@ export interface NftCreateData {
transferable: boolean
owner: string
}

export interface AccessListData {
name: string
symbol: string
tokenURI: string[]
transferable: boolean
owner: string
user: string[]
}
132 changes: 132 additions & 0 deletions src/contracts/AccessListFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { BigNumber, Signer } from 'ethers'
import { Config } from '../config'
import AccessListFactory from '@oceanprotocol/contracts/artifacts/contracts/accesslists/AccessListFactory.sol/AccessListFactory.json'
import { generateDtName, sendTx, getEventFromTx, ZERO_ADDRESS } from '../utils'
import { AbiItem, AccessListData, ReceiptOrEstimate } from '../@types'
import { SmartContractWithAddress } from './SmartContractWithAddress'
import * as sapphire from '@oasisprotocol/sapphire-paratime'

/**
* Provides an interface for Access List Factory contract
*/
export class AccesslistFactory extends SmartContractWithAddress {
getDefaultAbi() {
return AccessListFactory.abi as AbiItem[]
}

/**
* Instantiate AccessListFactory class
* @param {string} address The factory contract address.
* @param {Signer} signer The signer object.
* @param {string | number} [network] Network id or name
* @param {Config} [config] The configuration object.
* @param {AbiItem[]} [abi] ABI array of the smart contract
*/
constructor(
address: string,
signer: Signer,
network?: string | number,
config?: Config,
abi?: AbiItem[]
) {
super(address, signer, network, config, abi)
this.signer = sapphire.wrap(signer)
this.abi = abi || this.getDefaultAbi()
}

/**
* Create new Access List Contract
* @param {AccessListData} listData The data needed to create an NFT.
* @param {Boolean} [estimateGas] if True, return gas estimate
* @return {Promise<string|BigNumber>} The transaction hash or the gas estimate.
*/
public async deployAccessListContract<G extends boolean = false>(
listData: AccessListData,
estimateGas?: G
): Promise<G extends false ? string : BigNumber> {
if (!listData.name || !listData.symbol) {
const { name, symbol } = generateDtName()
listData.name = name
listData.symbol = symbol
}
if (!listData.transferable) listData.transferable = true
const estGas = await this.contract.estimateGas.deployAccessListContract(
listData.name,
listData.symbol,
listData.transferable,
listData.owner,
listData.user,
listData.tokenURI
)
if (estimateGas) return <G extends false ? string : BigNumber>estGas
// Invoke createToken function of the contract
const tx = await sendTx(
estGas,
this.signer,
this.config?.gasFeeMultiplier,
this.contract.functions.deployAccessListContract,
listData.name,
listData.symbol,
listData.transferable,
listData.owner,
listData.user,
listData.tokenURI
)
const trxReceipt = await tx.wait()
const events = getEventFromTx(trxReceipt, 'NewAccessList')
return events.args[0]
}

/**
* Get Factory Owner
* @return {Promise<string>} Factory Owner address
*/
public async getOwner(): Promise<string> {
const owner = await this.contract.owner()
return owner
}

/**
* Is a list contract soul bound?
* @param {String} contractAddress list contract address
* @return {Promise<boolean>} is soulbound?
*/
public async isSoulbound(contractAddress: string): Promise<boolean> {
const isSoulbound = await this.contract.isSoulBound(contractAddress)
return isSoulbound
}

/**
* changeTemplateAddress - only factory Owner
* @param {String} owner caller address
* @param {Number} templateAddress address of the template we want to change
* @param {Boolean} estimateGas if True, return gas estimate
* @return {Promise<ReceiptOrEstimate>} current token template count
*/
public async changeTemplateAddress<G extends boolean = false>(
owner: string,
templateAddress: string,
estimateGas?: G
): Promise<ReceiptOrEstimate<G>> {
if ((await this.getOwner()) !== owner) {
throw new Error(`Caller is not Factory Owner`)
}

if (templateAddress === ZERO_ADDRESS) {
throw new Error(`Template address cannot be ZERO address`)
}

const estGas = await this.contract.estimateGas.changeTemplateAddress(templateAddress)
if (estimateGas) return <ReceiptOrEstimate<G>>estGas

const trxReceipt = await sendTx(
estGas,
this.signer,
this.config?.gasFeeMultiplier,
this.contract.functions.changeTemplateAddress,
templateAddress
)

return <ReceiptOrEstimate<G>>trxReceipt
}
}
13 changes: 13 additions & 0 deletions test/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,16 @@ export const getAddresses = () => {
)
return data.development
}

export const getAddressesForSapphire = (testnet: boolean) => {
const data = JSON.parse(
// eslint-disable-next-line security/detect-non-literal-fs-filename
fs.readFileSync(
process.env.ADDRESS_FILE ||
`${homedir}/.ocean/ocean-contracts/artifacts/address.json`,
'utf8'
)
)
if (testnet) return data.oasis_saphire_testnet
return data.oasis_saphire
}
41 changes: 41 additions & 0 deletions test/scripts/sapphireTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import * as sapphire from '@oasisprotocol/sapphire-paratime'
import { ethers, Signer } from 'ethers'
import { getAddressesForSapphire } from '../config'
import { AccesslistFactory } from '../../src/contracts/AccessListFactory'
import { AccessListContract } from '../../src/contracts/AccessList'
import { AccessListData } from '../../src/@types'
import { ZERO_ADDRESS } from '../../src'
import { assert } from 'console'

describe('Sapphire tests', async () => {
const provider = sapphire.wrap(
ethers.getDefaultProvider(sapphire.NETWORKS.testnet.defaultGateway)
)
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider)

const addresses = await getAddressesForSapphire(true)
const listData: AccessListData = {
name: 'ListName',
symbol: 'ListSymbol',
tokenURI: ['https://oceanprotocol.com/nft/'],
transferable: true,
owner: await wallet.getAddress(),
user: [await wallet.getAddress(), ZERO_ADDRESS]
}
let factoryContract: AccesslistFactory
let listAddress: string
let accessListToken: AccessListContract

it('Create Access List factory', () => {
factoryContract = new AccesslistFactory(addresses.AccessListFactory, wallet, 23295)
assert(factoryContract !== null, 'factory not created')
})

it('Create Access List contract', async () => {
listData.owner = await wallet.getAddress()
listAddress = await factoryContract.deployAccessListContract(listData)
assert(listAddress !== null)
console.log('list address: ', listAddress)
accessListToken = new AccessListContract(wallet, 23295)
})
})

0 comments on commit 9695585

Please sign in to comment.