Browse Source

Pricing

master
Lev 2 years ago
parent
commit
b35dbb9283
  1. 31
      contracts/imports/dns-utils.fc
  2. 29
      contracts/main.ts
  3. 10
      contracts/nft-collection.fc
  4. 14
      test/creation.spec.ts

31
contracts/imports/dns-utils.fc

@ -172,6 +172,37 @@ int check_domain_string(slice domain) {
return (10, 1);
}
int price_function(int length, int multiplierx10, int steepness) {
;; length is the length of the domain, the price depends on it. The rest is the price config
;; multiplierx10 is the price multiplier, the default price is multiplied by multiplierx10 / 10
;; steepness (from 0 to 10) is the steepness of the price function,
;; 10 means the distribution is as in the function from `get_min_price_config` (the second number), 0 means the price is always the same, 50
int price = 50;
if (length == 3) {
price = 200;
}
if (length == 4) {
price = 100;
}
if (length == 5) {
price = 50;
}
if (length == 6) {
price = 40;
}
if (length == 7) {
price = 30;
}
if (length == 8) {
price = 20;
}
if (length >= 9) {
price = 10;
}
price = (steepness * price + (10 - steepness) * 50) / 10;
return price * one_ton * multiplierx10 / 10;
}
int get_min_price(int domain_bits_length, int now_time) {
(int start_min_price, int end_min_price) = get_min_price_config(domain_bits_length / 8);
start_min_price *= one_ton;

29
contracts/main.ts

@ -1,10 +1,10 @@
import BN from "bn.js";
import { Cell, beginCell, Address } from "ton";
import { C7Config, SmartContract } from "ton-contract-executor";
import {Cell, beginCell, Address} from "ton";
import {C7Config, SmartContract} from "ton-contract-executor";
import {encodeOffChainContent, makeSnakeCell} from "./utils";
import { randomBytes } from "crypto";
import { keyPairFromSeed, KeyPair, sign } from "ton-crypto";
import { ExpansionPanelActions } from "@material-ui/core";
import {randomBytes} from "crypto";
import {keyPairFromSeed, KeyPair, sign} from "ton-crypto";
import {ExpansionPanelActions} from "@material-ui/core";
// encode contract storage according to save_data() contract method
@ -36,11 +36,20 @@ export function data(params: { ownerAddress: Address; collectionAddress: Address
return beginCell().storeRef(data_cell).storeBuffer(params.publicKey).endCell();
}
export function collectionData(params: { code: Cell, ownerAddress: Address, ownerKey: number }): Cell {
export function collectionData(params: {
code: Cell, ownerAddress: Address, ownerKey: number,
price_multiplier?: number, price_steepness?: number
}): Cell {
if (params.price_multiplier == undefined) {
params.price_multiplier = 10;
}
if (params.price_steepness == undefined) {
params.price_steepness = 5;
}
return beginCell()
.storeRef(encodeOffChainContent("https://agorata.io/collection.json"))
.storeRef(params.code)
.storeRef(beginCell().endCell())
.storeRef(beginCell().storeUint(params.price_multiplier, 8).storeUint(params.price_steepness, 4).endCell())
.storeUint(params.ownerKey, 256)
.storeAddress(params.ownerAddress)
.endCell();
@ -54,7 +63,9 @@ export function setContractBalance(contract: SmartContract, balance: number) {
contract.setC7Config({balance: balance});
}
export function TON(): number { return 1000000000; }
export function TON(): number {
return 1000000000;
}
// message encoders for all ops (see contracts/imports/constants.fc for consts)
@ -80,7 +91,7 @@ export function instantBuySignature(receiverAddress: Address, issuedCollectionAd
return sign(althash.toBuffer(), privateKey);
}
export function instantBuyMessage(params: { receiverAddress: Address, issuedCollectionAddr: Address, price: number, domain: String, privateKey: Buffer}): Cell {
export function instantBuyMessage(params: { receiverAddress: Address, issuedCollectionAddr: Address, price: number, domain: String, privateKey: Buffer }): Cell {
let domainSnakeCell = makeSnakeCell(Buffer.from(params.domain));
let signature = instantBuySignature(params.receiverAddress, params.issuedCollectionAddr, params.price, domainSnakeCell, params.privateKey);
console.log(signature.toString("hex").toUpperCase());

10
contracts/nft-collection.fc

@ -41,7 +41,10 @@ int calcprice(slice domain, cell pricing) inline_ref {
throw_unless(201, len <= 126 * 8); ;; maxmimum 126 characters
throw_unless(202, mod(len, 8) == 0);
throw_unless(203, check_domain_string(domain));
return 100000; ;; todo
slice pr = pricing.begin_parse();
int multiplier = pr~load_uint(8);
int steepness = pr~load_uint(4);
return price_function(len / 8, multiplier, steepness);
}
cell calculate_nft_item_state_init(int item_index, cell nft_item_code) {
@ -138,6 +141,11 @@ cell get_nft_content(int index, cell individual_nft_content) method_id {
return individual_nft_content;
}
int get_price(slice domain) method_id {
var (content, nft_item_code, pricing, key, addr) = load_data();
return calcprice(domain, pricing);
}
(int, cell) dnsresolve(slice subdomain, int category) method_id {
throw_unless(70, mod(slice_bits(subdomain), 8) == 0);

14
test/creation.spec.ts

@ -33,13 +33,23 @@ describe("Creating items tests", () => {
const sendToSelfMessage = internalMessage({
from: ownerAddr,
body: main.createItem({ domain: "test" }),
value: new BN(10 * main.TON()),
value: new BN(100 * main.TON()),
});
const res = await contract.sendInternalMessage(sendToSelfMessage);
console.log(res);
expect(res.type).to.equal("success");
expect(res.exit_code).to.equal(0);
});
it("does not allow to buy an item if the price is too low", async () => {
main.setContractBalance(contract, 10 * main.TON());
let ownerAddr = randomAddress("owner");
const sendToSelfMessage = internalMessage({
from: ownerAddr,
body: main.createItem({ domain: "test" }),
value: new BN(10 * main.TON()),
});
const res = await contract.sendInternalMessage(sendToSelfMessage);
expect(res.type).to.equal("failed");
});
});

Loading…
Cancel
Save