const accountId = context.accountId ?? props.accountId; if (!accountId) { return "You need to login first or create new NEAR account here: https://shard.dog/go"; } State.init({ amount: "0.01", drops: "1", name: "", poapTitle: "Sunset Soiree by NEAR Toronto", poapDesc: "Elevate your weekend at the stunning Sunset Soiree. Nestled high above the city, the event offers breathtaking panoramic views of Lisbon, setting the stage for relaxed networking and unwinding. Guests can enjoy vibrant conversations, eclectic tunes, and the opportunity to connect with like-minded individuals, all while being inspired by the city's energy and Lisbon's captivating skyline charm.", img: null, desc: "", pw: "ssnt", publicKeys: [], privKeys: [], allPws: [], }); if (Storage.privateGet("key_list")) { let obj = Storage.privateGet("key_list"); State.update({ publicKeys: obj.publicKeys, privKeys: obj.privKeys, }); } const keypomContract = "v2.keypom.near"; const gatewayUrl = "https://near.org/rngtickets.near/widget/kp-ticket-handler"; const Yocto2Near = (amount) => new Big(amount).div(new Big(10).pow(24)).toString(); const Near2Yocto = (amount) => new Big(amount).times(new Big(10).pow(24)).toFixed().toString(); function fromHex(h) { var s = ""; for (var i = 0; i < h.length; i += 2) { s += String.fromCharCode(parseInt(h.substr(i, 2), 16)); } return decodeURIComponent(escape(s)); } function generatePasswords() { var allPass = []; var fullHashed1 = ""; var fullHashed2 = ""; state.publicKeys.forEach((e) => { var fullUnhashed = state.pw + e + "1"; console.log(`unhashed: ${fullUnhashed}`); asyncFetch("https://keypom.sctuts.com/hashpw/" + fullUnhashed).then( (res) => { var hashedJson = JSON.parse(res.body); fullHashed1 = hashedJson.pw; console.log(`hashed: ${fullHashed1}`); asyncFetch( "https://keypom.sctuts.com/hashpw/" + fullHashed1 + "/" + true ).then((result) => { var hashedJson2 = JSON.parse(result.body); fullHashed2 = hashedJson2.pw; allPass.push([ { pw: `${fullHashed2}`, key_use: 1, }, ]); console.log(`double hashed: ${fullHashed2}`); }); } ); }); var finalAllPass = allPass.reverse(); return finalAllPass; } const createDrop = () => { const newDropId = Date.now(); if (state.name) { newDropId = Number(state.name); } console.log(`State name: ${state.name}`); asyncFetch( "https://keypom.sctuts.com/keypair/" + state.drops + "/rootEntropy/" + newDropId.toString() ).then((res) => { let keyPairs = JSON.parse(res.body); console.log("keypairs:", keyPairs); let pubKeys = []; let privKeys = []; keyPairs.forEach((e) => { pubKeys.push(e.pub); privKeys.push(e.priv); }); let obj = { publicKeys: pubKeys, privKeys: privKeys, }; State.update(obj); const allPass = generatePasswords(); console.log(`AAAALLLL PASS: ${allPass}`); Storage.privateSet("key_list", obj); const calls = [ { contractName: keypomContract, methodName: "create_drop", gas: "100000000000000", args: { public_keys: state.publicKeys, deposit_per_use: Near2Yocto(state.amount ?? "0.05"), drop_id: newDropId.toString(), config: { uses_per_key: 2, }, passwords_per_use: allPass, fc: { methods: [ null, [ // mint NFT { receiver_id: `nft-v2.keypom.near`, method_name: "nft_mint", args: "", drop_id_field: "mint_id", account_id_field: "receiver_id", attached_deposit: Near2Yocto(0.1), }, ], ], }, }, deposit: Near2Yocto(0.1), }, ]; if (!state.name) { calls.unshift({ contractName: "nft-v2.keypom.near", methodName: "create_series", gas: "100000000000000", args: { mint_id: newDropId, metadata: { title: `${state.poapTitle}`, media: `https://ipfs.near.social/ipfs/${ state.img ? state.img.cid : "bafkreibqmnq7rlq2r2ov2a6yfkdwgr5gcgsiihnbr54g4ylrvdsnlym4pe" }`, description: `${state.poapDesc}`, copies: parseInt(`${state.drops}`), }, }, deposit: Near2Yocto(0.1), }); } Near.call(calls); }); }; const onChangeValue = (t, v) => { State.update({ [t]: v, }); if (t == "drops" && v > 100) { State.update({ drops: 100, }); } if (t == "name") { State.update({ name: v.replace(/\s+/g, "-").toLowerCase(), }); } if (t == "password") { State.update({ pw: v, }); } console.log(t + " : ", v); }; const getListLink = () => { let links = ""; state.privKeys.map((e, i) => { let data = JSON.stringify({ u: accountId, k: e }); //base64 encoded let link = gatewayUrl + "?key=" + state.publicKeys[i] + "&pk=" + state.privKeys[i]; links += link + " \n "; }); return links; }; const saveDropInfo = () => { let obj = { img: state.img.cid, desc: state.desc, }; console.log(obj); }; return ( <div className="mb-3 container row"> <div className="container"> <h2 className="mt-3">Create Ticket Drop</h2> <h4>Event Information</h4> <div className="input-field mt-3"> Drop id (leave empty to create new): <input type="string" value={state.name} onChange={(e) => onChangeValue("name", e.target.value)} /> Number of Tickets: <input type="number" min="1" max="100" defaultValue="2" value={state.drops} onChange={(e) => onChangeValue("drops", e.target.value)} /> NEAR per Drop: <input type="number" min="0" step="0.01" defaultValue="0.01" onChange={(e) => onChangeValue("amount", e.target.value)} /> Ticket Password (Case Sensitive): <input type="string" value={state.pw} onChange={(e) => onChangeValue("password", e.target.value)} /> </div> </div> {!state.name && ( <div className="container mt-3 pt-3 border-top border-3"> <div className="config-drop"> <h4>POAP Information</h4> {/*<h6 style={{ color: "orange" }}> Save this information before creating your drop </h6>*/} Set POAP Image <br /> <IpfsImageUpload image={state.img} /> <div className="mt-2"> {state.img && ( <img style={{ maxWidth: 500 }} src={`https://ipfs.near.social/ipfs/${ state.img.cid ?? state.img }`} alt="uploaded" /> )} </div> POAP Title: <input type="string" value={state.poapTitle} onChange={(e) => onChangeValue("poapTitle", e.target.value)} /> POAP Description: <input type="string" value={state.poapDesc} onChange={(e) => onChangeValue("poapDesc", e.target.value)} /> <br /> <Markdown className="mt-3" text={state.desc} /> {/* <CommitButton className="btn btn-info" data={{ keypomConfig: { img: state.img.cid ?? state.img, desc: state.desc, }, }} > Save linkdrop info </CommitButton> */} </div> </div> )} <button className="btn btn-lg btn-primary mt-3" onClick={(e) => createDrop()} > Create Ticket Drop </button> <div className="result-field mt-4 border-top border-3 "> <h2 className="mt-3">Results</h2> {state.publicKeys.length > 0 && ( <> <button className="btn btn-sm btn-dark" onClick={() => clipboard.writeText(JSON.stringify(getListLink()))} > Copy all {state.publicKeys.length} linkdrop to Clipboard </button> </> )} <br /> <small>Make sure to save these links to use later!</small> <div className="link-list"> {state.privKeys.length > 0 && state.privKeys.map((e, i) => { // let link = // "https://testnet.mynearwallet.com/linkdrop/v2.keypom.testnet/" + // e; let data = JSON.stringify({ u: accountId, k: e }); //base64 encoded let link = gatewayUrl + "?key=" + state.publicKeys[i] + "&pk=" + state.privKeys[i]; //Buffer.from(data, "utf-8").toString("base64") return ( <> <div class="input-group mb-3"> <a class="btn btn-outline-secondary" target="_blank" href={link} > {" "} Drop #{i + 1} </a>{" "} <br /> <button class="btn btn-outline-secondary" type="button" onClick={(e) => clipboard.writeText(link)} > Copy </button> </div> </> ); })} </div> </div> </div> );