-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #76 from hollow-leaf/feat/frontend_arch
feat: frontend_arch
- Loading branch information
Showing
32 changed files
with
1,474 additions
and
298 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { getitem } from "./search_ton_asset.js"; | ||
import { openWallet } from "./src/utils.js"; | ||
import { Collection } from "./src/contracts/NftCollection.js"; | ||
import { waitSeqno } from "./src/delay.js"; | ||
import { Address, toNano } from "ton-core"; | ||
import { NftItem } from "./src/contracts/NftItem.js"; | ||
import { NftMarketplace } from "./src/contracts/NftMarketplace.js" | ||
import { NftSale } from "./src/contracts/Sales.js"; | ||
|
||
|
||
|
||
export async function mint_nft(provider){ | ||
const nft = await getitem() | ||
const index = nft.length | ||
try{ | ||
let nft_address = await Mint(index) | ||
Salenft(index, provider) | ||
return nft_address | ||
}catch(err){ | ||
console.log(err) | ||
} | ||
} | ||
|
||
async function Mint(index) { | ||
const wallet = await openWallet(process.env.MNEMONIC.split(" "), true); | ||
const collectionData = { | ||
ownerAddress: wallet.contract.address, | ||
royaltyPercent: 0, // 0.05 = 5% | ||
royaltyAddress: wallet.contract.address, | ||
nextItemIndex: 0, | ||
collectionContentUrl: `ipfs://`, | ||
commonContentUrl: `ipfs://`, | ||
}; | ||
const collection = new Collection(collectionData); | ||
|
||
console.log(`Start deploy of NFT`); | ||
const mintParams = { | ||
queryId: 0, | ||
itemOwnerAddress: wallet.contract.address, | ||
itemIndex: index, | ||
amount: toNano("0.05"), | ||
commonContentUrl: "", | ||
}; | ||
|
||
const nftItem = new NftItem(collection); | ||
const seqno = await nftItem.deploy(wallet, mintParams); | ||
console.log(`Successfully deployed NFT`); | ||
await waitSeqno(seqno, wallet); | ||
return (await NftItem.getAddressByIndex(collection.address, index)).toRawString() | ||
} | ||
|
||
async function Salenft(index, provider) { | ||
const wallet = await openWallet(process.env.MNEMONIC.split(" "), true); | ||
const collectionData = { | ||
ownerAddress: wallet.contract.address, | ||
royaltyPercent: 0, // 0.05 = 5% | ||
royaltyAddress: wallet.contract.address, | ||
nextItemIndex: 0, | ||
collectionContentUrl: `ipfs://`, | ||
commonContentUrl: `ipfs://`, | ||
}; | ||
const collection = new Collection(collectionData); | ||
const marketplace = new NftMarketplace(wallet.contract.address); | ||
const nftToSaleAddress = await NftItem.getAddressByIndex(collection.address, index); | ||
|
||
const saleData = { | ||
isComplete: false, | ||
createdAt: Math.ceil(Date.now() / 1000), | ||
marketplaceAddress: marketplace.address, | ||
nftAddress: nftToSaleAddress, | ||
nftOwnerAddress: Address.parse(provider), | ||
fullPrice: toNano("1"), | ||
marketplaceFeeAddress: wallet.contract.address, | ||
marketplaceFee: toNano("0"), | ||
royaltyAddress: wallet.contract.address, | ||
royaltyAmount: toNano("0"), | ||
}; | ||
const nftSaleContract = new NftSale(saleData); | ||
const seqno = await nftSaleContract.deploy(wallet); | ||
await waitSeqno(seqno, wallet); | ||
|
||
NftItem.transfer(wallet, nftSaleContract.address, nftToSaleAddress); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import axios from "axios"; | ||
|
||
|
||
export async function getitem() { | ||
try { | ||
const res = await axios({ | ||
method: 'get', | ||
url: `https://testnet.tonapi.io/v2/nfts/collections/EQDW1G_c_xIb2Iyzof123IAzQlY942Pl3H6XEJ_jRB2ez-Pe/items?limit=1000&offset=0`, | ||
}) | ||
console.log(res) | ||
return res.data["nft_items"] | ||
} | ||
catch (err) { | ||
console.log("error", err); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import { | ||
Cell, | ||
internal, | ||
beginCell, | ||
contractAddress, | ||
SendMode, | ||
} from "ton-core"; | ||
import { encodeOffChainContent } from "../utils.js"; | ||
|
||
|
||
|
||
export class Collection { | ||
collectionData; | ||
|
||
constructor(collectionData) { | ||
this.collectionData = collectionData; | ||
} | ||
|
||
createCodeCell() { | ||
const NftCollectionCodeBoc = | ||
"te6cckECFAEAAh8AART/APSkE/S88sgLAQIBYgkCAgEgBAMAJbyC32omh9IGmf6mpqGC3oahgsQCASAIBQIBIAcGAC209H2omh9IGmf6mpqGAovgngCOAD4AsAAvtdr9qJofSBpn+pqahg2IOhph+mH/SAYQAEO4tdMe1E0PpA0z/U1NQwECRfBNDUMdQw0HHIywcBzxbMyYAgLNDwoCASAMCwA9Ra8ARwIfAFd4AYyMsFWM8WUAT6AhPLaxLMzMlx+wCAIBIA4NABs+QB0yMsCEsoHy//J0IAAtAHIyz/4KM8WyXAgyMsBE/QA9ADLAMmAE59EGOASK3wAOhpgYC42Eit8H0gGADpj+mf9qJofSBpn+pqahhBCDSenKgpQF1HFBuvgoDoQQhUZYBWuEAIZGWCqALnixJ9AQpltQnlj+WfgOeLZMAgfYBwGyi544L5cMiS4ADxgRLgAXGBEuAB8YEYGYHgAkExIREAA8jhXU1DAQNEEwyFAFzxYTyz/MzMzJ7VTgXwSED/LwACwyNAH6QDBBRMhQBc8WE8s/zMzMye1UAKY1cAPUMI43gED0lm+lII4pBqQggQD6vpPywY/egQGTIaBTJbvy9AL6ANQwIlRLMPAGI7qTAqQC3gSSbCHis+YwMlBEQxPIUAXPFhPLP8zMzMntVABgNQLTP1MTu/LhklMTugH6ANQwKBA0WfAGjhIBpENDyFAFzxYTyz/MzMzJ7VSSXwXiN0CayQ=="; | ||
return Cell.fromBase64(NftCollectionCodeBoc); | ||
} | ||
|
||
createDataCell() { | ||
const data = this.collectionData; | ||
const dataCell = beginCell(); | ||
|
||
dataCell.storeAddress(data.ownerAddress); | ||
dataCell.storeUint(data.nextItemIndex, 64); | ||
|
||
const contentCell = beginCell(); | ||
|
||
const collectionContent = encodeOffChainContent(data.collectionContentUrl); | ||
|
||
const commonContent = beginCell(); | ||
commonContent.storeBuffer(Buffer.from(data.commonContentUrl)); | ||
|
||
contentCell.storeRef(collectionContent); | ||
contentCell.storeRef(commonContent.asCell()); | ||
dataCell.storeRef(contentCell); | ||
const NftItemCodeCell = Cell.fromBase64( | ||
"te6cckECDQEAAdAAART/APSkE/S88sgLAQIBYgMCAAmhH5/gBQICzgcEAgEgBgUAHQDyMs/WM8WAc8WzMntVIAA7O1E0NM/+kAg10nCAJp/AfpA1DAQJBAj4DBwWW1tgAgEgCQgAET6RDBwuvLhTYALXDIhxwCSXwPg0NMDAXGwkl8D4PpA+kAx+gAxcdch+gAx+gAw8AIEs44UMGwiNFIyxwXy4ZUB+kDUMBAj8APgBtMf0z+CEF/MPRRSMLqOhzIQN14yQBPgMDQ0NTWCEC/LJqISuuMCXwSED/LwgCwoAcnCCEIt3FzUFyMv/UATPFhAkgEBwgBDIywVQB88WUAX6AhXLahLLH8s/Im6zlFjPFwGRMuIByQH7AAH2UTXHBfLhkfpAIfAB+kDSADH6AIIK+vCAG6EhlFMVoKHeItcLAcMAIJIGoZE24iDC//LhkiGOPoIQBRONkchQCc8WUAvPFnEkSRRURqBwgBDIywVQB88WUAX6AhXLahLLH8s/Im6zlFjPFwGRMuIByQH7ABBHlBAqN1viDACCAo41JvABghDVMnbbEDdEAG1xcIAQyMsFUAfPFlAF+gIVy2oSyx/LPyJus5RYzxcBkTLiAckB+wCTMDI04lUC8ANqhGIu" | ||
); | ||
dataCell.storeRef(NftItemCodeCell); | ||
const royaltyBase = 1000; | ||
const royaltyFactor = Math.floor(data.royaltyPercent * royaltyBase); | ||
|
||
const royaltyCell = beginCell(); | ||
royaltyCell.storeUint(royaltyFactor, 16); | ||
royaltyCell.storeUint(royaltyBase, 16); | ||
royaltyCell.storeAddress(data.royaltyAddress); | ||
dataCell.storeRef(royaltyCell); | ||
|
||
return dataCell.endCell(); | ||
} | ||
|
||
get stateInit() { | ||
const code = this.createCodeCell(); | ||
const data = this.createDataCell(); | ||
|
||
return { code, data }; | ||
} | ||
|
||
get address() { | ||
return contractAddress(0, this.stateInit); | ||
} | ||
|
||
async deploy(wallet) { | ||
const seqno = await wallet.contract.getSeqno(); | ||
await wallet.contract.sendTransfer({ | ||
seqno, | ||
secretKey: wallet.keyPair.secretKey, | ||
messages: [ | ||
internal({ | ||
value: "0.05", | ||
to: this.address, | ||
init: this.stateInit, | ||
}), | ||
], | ||
sendMode: SendMode.PAY_GAS_SEPARATELY + SendMode.IGNORE_ERRORS, | ||
}); | ||
return seqno; | ||
} | ||
|
||
async topUpBalance( | ||
wallet, | ||
nftAmount | ||
) { | ||
const feeAmount = 0.026 // approximate value of fees for 1 transaction in our case | ||
const seqno = await wallet.contract.getSeqno(); | ||
const amount = nftAmount * feeAmount; | ||
|
||
await wallet.contract.sendTransfer({ | ||
seqno, | ||
secretKey: wallet.keyPair.secretKey, | ||
messages: [ | ||
internal({ | ||
value: amount.toString(), | ||
to: this.address.toString({ bounceable: false }), | ||
body: new Cell(), | ||
}), | ||
], | ||
sendMode: SendMode.PAY_GAS_SEPARATELY + SendMode.IGNORE_ERRORS, | ||
}); | ||
|
||
return seqno; | ||
} | ||
|
||
createMintBody(params){ | ||
const body = beginCell(); | ||
body.storeUint(1, 32); | ||
body.storeUint(params.queryId || 0, 64); | ||
body.storeUint(params.itemIndex, 64); | ||
body.storeCoins(params.amount); | ||
const nftItemContent = beginCell(); | ||
nftItemContent.storeAddress(params.itemOwnerAddress); | ||
|
||
const uriContent = beginCell(); | ||
uriContent.storeBuffer(Buffer.from(params.commonContentUrl)); | ||
nftItemContent.storeRef(uriContent.endCell()); | ||
|
||
body.storeRef(nftItemContent.endCell()); | ||
return body.endCell(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { Address, beginCell, Cell, internal, SendMode } from "ton-core"; | ||
import { TonClient } from "ton"; | ||
|
||
export class NftItem { | ||
collection; | ||
|
||
constructor(collection) { | ||
this.collection = collection; | ||
} | ||
|
||
async deploy( | ||
wallet, | ||
params | ||
){ | ||
const seqno = await wallet.contract.getSeqno(); | ||
await wallet.contract.sendTransfer({ | ||
seqno, | ||
secretKey: wallet.keyPair.secretKey, | ||
messages: [ | ||
internal({ | ||
value: "0.05", | ||
to: this.collection.address, | ||
body: this.collection.createMintBody(params), | ||
}), | ||
], | ||
sendMode: SendMode.IGNORE_ERRORS + SendMode.PAY_GAS_SEPARATELY, | ||
}); | ||
return seqno; | ||
} | ||
|
||
static async getAddressByIndex( | ||
collectionAddress, | ||
itemIndex | ||
) { | ||
const client = new TonClient({ | ||
endpoint: "https://testnet.toncenter.com/api/v2/jsonRPC", | ||
apiKey: process.env.TONCENTER_API_KEY, | ||
}); | ||
|
||
const response = await client.runMethod( | ||
collectionAddress, | ||
"get_nft_address_by_index", | ||
[{ type: "int", value: BigInt(itemIndex) }] | ||
); | ||
return response.stack.readAddress(); | ||
} | ||
|
||
static createTransferBody(params) { | ||
const msgBody = beginCell(); | ||
msgBody.storeUint(0x5fcc3d14, 32); // op-code | ||
msgBody.storeUint(0, 64); // query-id | ||
msgBody.storeAddress(params.newOwner); | ||
msgBody.storeAddress(params.responseTo || null); | ||
msgBody.storeBit(false); // no custom payload | ||
msgBody.storeCoins(params.forwardAmount || 0); | ||
msgBody.storeBit(0); // no forward_payload | ||
|
||
return msgBody.endCell(); | ||
} | ||
|
||
|
||
static async transfer( | ||
wallet, | ||
new_owner, | ||
itemaddress | ||
) { | ||
const seqno = await wallet.contract.getSeqno(); | ||
const body = NftItem.createTransferBody({newOwner:new_owner, responseTo: wallet.contract.address}) | ||
|
||
await wallet.contract.sendTransfer({ | ||
seqno, | ||
secretKey: wallet.keyPair.secretKey, | ||
messages: [ | ||
internal({ | ||
value: "0.05", | ||
to: itemaddress, | ||
body: body, | ||
}), | ||
], | ||
sendMode: SendMode.IGNORE_ERRORS + SendMode.PAY_GAS_SEPARATELY, | ||
}); | ||
return seqno; | ||
} | ||
|
||
|
||
} |
Oops, something went wrong.