-
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.
Chain: Add Mint Functionality to Each Chain
- Loading branch information
Showing
12 changed files
with
267 additions
and
10 deletions.
There are no files selected for viewing
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
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
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
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,159 @@ | ||
import { | ||
Address, | ||
Cell, | ||
OpenedContract, | ||
SendMode, | ||
Sender, | ||
StateInit, | ||
beginCell, | ||
contractAddress, | ||
internal, | ||
} from "@ton/core"; | ||
import { KeyPair } from "@ton/crypto"; | ||
import { WalletContractV4 } from "@ton/ton"; | ||
|
||
export type collectionData = { | ||
ownerAddress: Address; | ||
royaltyPercent: number; | ||
royaltyAddress: Address; | ||
nextItemIndex: number; | ||
collectionContentUrl: string; | ||
commonContentUrl: string; | ||
}; | ||
|
||
export class TonNftCollection { | ||
private collectionData: collectionData; | ||
|
||
constructor(collectionData: collectionData) { | ||
this.collectionData = collectionData; | ||
} | ||
|
||
private createCodeCell(): Cell { | ||
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); | ||
} | ||
|
||
private createDataCell(): Cell { | ||
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(); | ||
} | ||
|
||
public get stateInit(): StateInit { | ||
const code = this.createCodeCell(); | ||
const data = this.createDataCell(); | ||
|
||
return { code, data }; | ||
} | ||
public get address(): Address { | ||
return contractAddress(0, this.stateInit); | ||
} | ||
|
||
public async deploy(contract: Sender) { | ||
await contract.send({ | ||
to: this.address, | ||
init: this.stateInit, | ||
value: 500000n, | ||
sendMode: SendMode.PAY_GAS_SEPARATELY + SendMode.IGNORE_ERRORS, | ||
}); | ||
return; | ||
} | ||
|
||
public async topUpBalance( | ||
wallet: OpenedWallet, | ||
nftAmount: number, | ||
): Promise<number> { | ||
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; | ||
} | ||
} | ||
|
||
type OpenedWallet = { | ||
contract: OpenedContract<WalletContractV4>; | ||
keyPair: KeyPair; | ||
}; | ||
|
||
export function encodeOffChainContent(content: string) { | ||
let data = Buffer.from(content); | ||
const offChainPrefix = Buffer.from([0x01]); | ||
data = Buffer.concat([offChainPrefix, data]); | ||
return makeSnakeCell(data); | ||
} | ||
function makeSnakeCell(data: Buffer): Cell { | ||
const chunks = bufferToChunks(data, 127); | ||
|
||
if (chunks.length === 0) { | ||
return beginCell().endCell(); | ||
} | ||
|
||
if (chunks.length === 1) { | ||
return beginCell().storeBuffer(chunks[0]).endCell(); | ||
} | ||
|
||
let curCell = beginCell(); | ||
|
||
for (let i = chunks.length - 1; i >= 0; i--) { | ||
const chunk = chunks[i]; | ||
|
||
curCell.storeBuffer(chunk); | ||
|
||
if (i - 1 >= 0) { | ||
const nextCell = beginCell(); | ||
nextCell.storeRef(curCell); | ||
curCell = nextCell; | ||
} | ||
} | ||
|
||
return curCell.endCell(); | ||
} | ||
function bufferToChunks(buff: Buffer, chunkSize: number) { | ||
const chunks: Buffer[] = []; | ||
while (buff.byteLength > 0) { | ||
chunks.push(buff.subarray(0, chunkSize)); | ||
//biome-ignore lint/style/noParameterAssign: weird code from ton copy pasta | ||
buff = buff.subarray(chunkSize); | ||
} | ||
return chunks; | ||
} |
Oops, something went wrong.