├── README.md ├── src ├── react-app-env.d.ts ├── img │ ├── Jp.png │ ├── Chris.png │ ├── Paulina.png │ ├── Savana.png │ ├── Sophia.png │ ├── Jonathan.png │ ├── bg │ │ ├── main-bg-1.jpg │ │ └── sbb-main-bkg.jpg │ └── solbot-about.png ├── utils │ ├── mx │ │ ├── constants │ │ │ ├── index.ts │ │ │ ├── math.ts │ │ │ └── labels.ts │ │ ├── models │ │ │ ├── index.ts │ │ │ └── account.ts │ │ ├── types │ │ │ ├── jazzicon.d.ts │ │ │ ├── u64.d.ts │ │ │ └── buffer-layout.d.ts │ │ ├── utils │ │ │ ├── isValidHttpUrl.ts │ │ │ ├── index.tsx │ │ │ ├── notifications.tsx │ │ │ ├── shortvec.ts │ │ │ ├── useLocalStorage.ts │ │ │ ├── borsh.ts │ │ │ ├── createPipelineExecutor.ts │ │ │ ├── programIds.ts │ │ │ ├── eventEmitter.ts │ │ │ ├── assets.ts │ │ │ ├── strings.ts │ │ │ ├── ids.ts │ │ │ ├── layout.ts │ │ │ └── utils.ts │ │ ├── contexts │ │ │ ├── accounts │ │ │ │ ├── parsesrs.ts │ │ │ │ └── deserialize.ts │ │ │ └── connection.tsx │ │ ├── account.ts │ │ └── metadata.ts │ ├── constant.ts │ ├── ntfs.ts │ └── nft.ts ├── setupTests.js ├── App.test.js ├── components │ ├── VideoBG │ │ └── index.js │ ├── Navbar │ │ └── index.js │ ├── About │ │ └── index.js │ ├── Pro │ │ └── index.js │ ├── ComingSoon │ │ └── index.js │ ├── TimeLine │ │ └── index.js │ ├── Faq │ │ └── index.js │ └── Slider │ │ └── index.js ├── reportWebVitals.js ├── App.css ├── index.js ├── index.css └── App.js ├── public ├── logo.png ├── favicon.ico ├── logo192.png ├── logo512.png ├── robots.txt ├── css │ ├── plugins │ │ ├── close.png │ │ ├── owl.theme.default.min.css │ │ ├── YouTubePopUp.css │ │ ├── owl.carousel.min.css │ │ └── magnific-popup.css │ ├── plugins.min.css │ └── style.min.css ├── fonts │ ├── Rajdhani-Regular.woff │ ├── BalonkuRegular-la1.woff │ └── CutiePatootie-Rgjv.woff ├── mixkit-retro-arcade-casino-notification-211.wav ├── manifest.json ├── js │ ├── scrollIt.min.js │ ├── YouTubePopUp.js │ ├── custom.js │ └── pace.js └── index.html ├── GIT_PUSH.bat ├── .gitignore ├── tsconfig.json └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # solanabeachbot 2 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/img/Jp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/src/img/Jp.png -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/public/logo.png -------------------------------------------------------------------------------- /src/img/Chris.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/src/img/Chris.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/public/logo512.png -------------------------------------------------------------------------------- /src/img/Paulina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/src/img/Paulina.png -------------------------------------------------------------------------------- /src/img/Savana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/src/img/Savana.png -------------------------------------------------------------------------------- /src/img/Sophia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/src/img/Sophia.png -------------------------------------------------------------------------------- /src/img/Jonathan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/src/img/Jonathan.png -------------------------------------------------------------------------------- /src/utils/mx/constants/index.ts: -------------------------------------------------------------------------------- 1 | export * from './math'; 2 | export * from './labels'; 3 | -------------------------------------------------------------------------------- /src/utils/mx/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from './account'; 2 | //export * from './metaplex'; 3 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/img/bg/main-bg-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/src/img/bg/main-bg-1.jpg -------------------------------------------------------------------------------- /src/img/solbot-about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/src/img/solbot-about.png -------------------------------------------------------------------------------- /src/img/bg/sbb-main-bkg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/src/img/bg/sbb-main-bkg.jpg -------------------------------------------------------------------------------- /public/css/plugins/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/public/css/plugins/close.png -------------------------------------------------------------------------------- /public/fonts/Rajdhani-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/public/fonts/Rajdhani-Regular.woff -------------------------------------------------------------------------------- /public/fonts/BalonkuRegular-la1.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/public/fonts/BalonkuRegular-la1.woff -------------------------------------------------------------------------------- /public/fonts/CutiePatootie-Rgjv.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/public/fonts/CutiePatootie-Rgjv.woff -------------------------------------------------------------------------------- /src/utils/mx/types/jazzicon.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'jazzicon' { 2 | const jazzicon: any; 3 | export = jazzicon; 4 | } 5 | -------------------------------------------------------------------------------- /public/mixkit-retro-arcade-casino-notification-211.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eros1006/SBot/HEAD/public/mixkit-retro-arcade-casino-notification-211.wav -------------------------------------------------------------------------------- /src/utils/mx/types/u64.d.ts: -------------------------------------------------------------------------------- 1 | import BN from 'bn.js'; 2 | 3 | export class u64 extends BN { 4 | toBuffer(): Buffer; 5 | static fromBuffer(buffer: Buffer): u64; 6 | } 7 | -------------------------------------------------------------------------------- /GIT_PUSH.bat: -------------------------------------------------------------------------------- 1 | git init 2 | git add . 3 | git commit -m "first commit" 4 | git branch -M main 5 | git remote add origin https://github.com/mymiracle0118/SBot.git 6 | git push -u origin main -------------------------------------------------------------------------------- /src/utils/mx/utils/isValidHttpUrl.ts: -------------------------------------------------------------------------------- 1 | export function isValidHttpUrl(text: string) { 2 | if (text.startsWith('http:') || text.startsWith('https:')) { 3 | return true; 4 | } 5 | 6 | return false; 7 | } 8 | -------------------------------------------------------------------------------- /src/utils/mx/types/buffer-layout.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'buffer-layout' { 2 | const bl: any; 3 | export = bl; 4 | } 5 | 6 | declare module 'jazzicon' { 7 | const jazzicon: any; 8 | export = jazzicon; 9 | } 10 | -------------------------------------------------------------------------------- /src/utils/mx/constants/math.ts: -------------------------------------------------------------------------------- 1 | import BN from 'bn.js'; 2 | 3 | export const TEN = new BN(10); 4 | export const HALF_WAD = TEN.pow(new BN(18)); 5 | export const WAD = TEN.pow(new BN(18)); 6 | export const RAY = TEN.pow(new BN(27)); 7 | export const ZERO = new BN(0); 8 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /public/css/plugins.min.css: -------------------------------------------------------------------------------- 1 | @import url("https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.1/css/bootstrap.min.css"); 2 | @import url("plugins/animate.min.css"); 3 | @import url("plugins/magnific-popup.css"); 4 | @import url("plugins/owl.carousel.min.css"); 5 | @import url("plugins/owl.theme.default.min.css"); 6 | @import url("plugins/YouTubePopUp.css"); 7 | .pt-40 { 8 | padding-top: 40px; 9 | } -------------------------------------------------------------------------------- /src/components/VideoBG/index.js: -------------------------------------------------------------------------------- 1 | import backImg from '../../img/bg/sbb-main-bkg.jpg' 2 | 3 | function VideoBG() { 4 | return ( 5 |
6 | {/* */} 9 | no back 10 |
11 | ) 12 | } 13 | 14 | export default VideoBG -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | .certbot 26 | -------------------------------------------------------------------------------- /src/utils/mx/utils/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './eventEmitter'; 2 | export * from './ids'; 3 | export * from './programIds'; 4 | export * as Layout from './layout'; 5 | export * from './notifications'; 6 | export * from './utils'; 7 | export * from './useLocalStorage'; 8 | export * from './strings'; 9 | export * as shortvec from './shortvec'; 10 | export * from './isValidHttpUrl'; 11 | export * from './borsh'; 12 | export * from './createPipelineExecutor'; 13 | -------------------------------------------------------------------------------- /src/utils/constant.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublicKey, 3 | } from '@solana/web3.js' 4 | 5 | export const update_authority_key = new PublicKey('FnKXCAbNzvAGKtTqSxH2NrWemR4CoJhCMrdk4ihBG2P6') 6 | 7 | export const NFTINTERFACEPREFIX = 'nftinterface' 8 | export const TOKENPREFIX = 'tokenid' 9 | export const programId = new PublicKey('67Ub7H8Vbo9avcmskKDUN7yzDrsZbqZaJHGW22eDkXxM') 10 | 11 | 12 | export const fee_receiver_key1 = new PublicKey('4pMhWwcw9C1pYW4zLMX5R8FHPuBMrCiX1VuX1ignEiBV') -------------------------------------------------------------------------------- /src/utils/mx/utils/notifications.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export function notify({ 4 | message = '', 5 | description = undefined as any, 6 | txid = '', 7 | type = 'info', 8 | placement = 'bottomLeft', 9 | }) { 10 | if (txid) { 11 | // 16 | // View transaction {txid.slice(0, 8)}...{txid.slice(txid.length - 8)} 17 | // 18 | 19 | description = <>; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "downlevelIteration": true, 21 | "noEmit": true, 22 | "jsx": "react-jsx" 23 | }, 24 | "include": [ 25 | "src" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /src/utils/mx/utils/shortvec.ts: -------------------------------------------------------------------------------- 1 | export function decodeLength(bytes: Array): number { 2 | let len = 0; 3 | let size = 0; 4 | for (;;) { 5 | const elem = bytes.shift(); 6 | //@ts-ignore 7 | len |= (elem & 0x7f) << (size * 7); 8 | size += 1; 9 | //@ts-ignore 10 | if ((elem & 0x80) === 0) { 11 | break; 12 | } 13 | } 14 | return len; 15 | } 16 | 17 | export function encodeLength(bytes: Array, len: number) { 18 | let rem_len = len; 19 | for (;;) { 20 | let elem = rem_len & 0x7f; 21 | rem_len >>= 7; 22 | if (rem_len === 0) { 23 | bytes.push(elem); 24 | break; 25 | } else { 26 | elem |= 0x80; 27 | bytes.push(elem); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | // import './style.css' 5 | import App from './App'; 6 | import reportWebVitals from './reportWebVitals'; 7 | import { toast, ToastContainer } from 'react-toastify' 8 | 9 | ReactDOM.render( 10 | 11 |
12 | 13 | 14 |
, 15 | document.getElementById('root') 16 | ); 17 | 18 | // If you want to start measuring performance in your app, pass a function 19 | // to log results (for example: reportWebVitals(console.log)) 20 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 21 | reportWebVitals(); 22 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Rubik:wght@300&display=swap'); 2 | 3 | 4 | /* html, body { 5 | width: 100%; 6 | height: 100vh; 7 | margin: 0; 8 | padding: 0; 9 | background-color: #1D1D1D; 10 | } */ 11 | 12 | /* body { 13 | margin: 0; 14 | font-family: 'Rubik'; 15 | color: #254cdd; 16 | -webkit-font-smoothing: antialiased; 17 | -moz-osx-font-smoothing: grayscale; 18 | } 19 | 20 | code { 21 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 22 | monospace; 23 | } */ 24 | 25 | .progress-bar { 26 | display: block; 27 | height: 100%; 28 | background: linear-gradient(90deg,#3f78ff,#ea4aaa 17%,#b34bff 34%,#01feff 51%,#ffd33d 68%,#ea4aaa 85%,#b34bff); 29 | background-size: 300% 100%; 30 | animation: progress-animation 2s linear infinite; 31 | } -------------------------------------------------------------------------------- /src/utils/mx/utils/useLocalStorage.ts: -------------------------------------------------------------------------------- 1 | type UseStorageReturnValue = { 2 | getItem: (key: string) => string; 3 | setItem: (key: string, value: string) => boolean; 4 | removeItem: (key: string) => void; 5 | }; 6 | 7 | export const UseLocalStorage = (): UseStorageReturnValue => { 8 | const isBrowser: boolean = ((): boolean => typeof window !== 'undefined')(); 9 | 10 | const getItem = (key: string): string => { 11 | return isBrowser ? window.localStorage[key] : ''; 12 | }; 13 | 14 | const setItem = (key: string, value: string): boolean => { 15 | if (isBrowser) { 16 | window.localStorage.setItem(key, value); 17 | return true; 18 | } 19 | 20 | return false; 21 | }; 22 | 23 | const removeItem = (key: string): void => { 24 | window.localStorage.removeItem(key); 25 | }; 26 | 27 | return { 28 | getItem, 29 | setItem, 30 | removeItem, 31 | }; 32 | }; 33 | -------------------------------------------------------------------------------- /public/css/plugins/owl.theme.default.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Owl Carousel v2.2.0 3 | * Copyright 2013-2016 David Deutsch 4 | * Licensed under MIT (https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE) 5 | */ 6 | .owl-theme .owl-dots,.owl-theme .owl-nav{text-align:center;-webkit-tap-highlight-color:transparent}.owl-theme .owl-nav{margin-top:10px}.owl-theme .owl-nav [class*=owl-]{color:#FFF;font-size:14px;margin:5px;padding:4px 7px;background:#D6D6D6;display:inline-block;cursor:pointer;border-radius:3px}.owl-theme .owl-nav [class*=owl-]:hover{background:#869791;color:#FFF;text-decoration:none}.owl-theme .owl-nav .disabled{opacity:.5;cursor:default}.owl-theme .owl-nav.disabled+.owl-dots{margin-top:10px}.owl-theme .owl-dots .owl-dot{display:inline-block;zoom:1}.owl-theme .owl-dots .owl-dot span{width:10px;height:10px;margin:5px 7px;background:#D6D6D6;display:block;-webkit-backface-visibility:visible;transition:opacity .2s ease;border-radius:30px}.owl-theme .owl-dots .owl-dot.active span,.owl-theme .owl-dots .owl-dot:hover span{background:#869791} -------------------------------------------------------------------------------- /src/utils/mx/constants/labels.ts: -------------------------------------------------------------------------------- 1 | export const LABELS = { 2 | CONNECT_LABEL: 'Connect Wallet', 3 | AUDIT_WARNING: 4 | 'Oyster is an unaudited software project used for internal purposes at the Solana Foundation. This app is not for public use.', 5 | FOOTER: 6 | 'This page was produced by the Solana Foundation ("SF") for internal educational and inspiration purposes only. SF does not encourage, induce or sanction the deployment, integration or use of Oyster or any similar application (including its code) in violation of applicable laws or regulations and hereby prohibits any such deployment, integration or use. Anyone using this code or a derivation thereof must comply with applicable laws and regulations when releasing related software.', 7 | MENU_HOME: 'Home', 8 | MENU_DASHBOARD: 'Dashboard', 9 | CONNECT_BUTTON: 'Connect', 10 | WALLET_TOOLTIP: 'Wallet public key', 11 | WALLET_BALANCE: 'Wallet balance', 12 | SETTINGS_TOOLTIP: 'Settings', 13 | DASHBOARD_ACTION: 'Go to dashboard', 14 | GO_BACK_ACTION: 'Go back', 15 | }; 16 | -------------------------------------------------------------------------------- /src/utils/mx/utils/borsh.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from '@solana/web3.js'; 2 | import { BinaryReader, BinaryWriter } from 'borsh'; 3 | import base58 from 'bs58'; 4 | import { StringPublicKey } from './ids'; 5 | 6 | export const extendBorsh = () => { 7 | (BinaryReader.prototype as any).readPubkey = function () { 8 | const reader = this as unknown as BinaryReader; 9 | const array = reader.readFixedArray(32); 10 | return new PublicKey(array); 11 | }; 12 | 13 | (BinaryWriter.prototype as any).writePubkey = function (value: PublicKey) { 14 | const writer = this as unknown as BinaryWriter; 15 | writer.writeFixedArray(value.toBuffer()); 16 | }; 17 | 18 | (BinaryReader.prototype as any).readPubkeyAsString = function () { 19 | const reader = this as unknown as BinaryReader; 20 | const array = reader.readFixedArray(32); 21 | return base58.encode(array) as StringPublicKey; 22 | }; 23 | 24 | (BinaryWriter.prototype as any).writePubkeyAsString = function ( 25 | value: StringPublicKey, 26 | ) { 27 | const writer = this as unknown as BinaryWriter; 28 | writer.writeFixedArray(base58.decode(value)); 29 | }; 30 | }; 31 | 32 | extendBorsh(); 33 | -------------------------------------------------------------------------------- /src/components/Navbar/index.js: -------------------------------------------------------------------------------- 1 | function Navbar() { 2 | return ( 3 | 29 | ) 30 | } 31 | 32 | export default Navbar -------------------------------------------------------------------------------- /public/js/scrollIt.min.js: -------------------------------------------------------------------------------- 1 | (function(e){"use strict";var t="ScrollIt",n="1.0.3";var r={upKey:38,downKey:40,easing:"linear",scrollTime:600,activeClass:"active",onPageChange:null,topOffset:0};e.scrollIt=function(t){var n=e.extend(r,t),i=0,s=e("[data-scroll-index]:last").attr("data-scroll-index");var o=function(t){if(t<0||t>s)return;var r=e("[data-scroll-index="+t+"]").offset().top+n.topOffset+1;e("html,body").animate({scrollTop:r,easing:n.easing},n.scrollTime)};var u=function(t){var n=e(t.target).closest("[data-scroll-nav]").attr("data-scroll-nav")||e(t.target).closest("[data-scroll-goto]").attr("data-scroll-goto");o(parseInt(n))};var a=function(t){var r=t.which;if(e("html,body").is(":animated")&&(r==n.upKey||r==n.downKey)){return false}if(r==n.upKey&&i>0){o(parseInt(i)-1);return false}else if(r==n.downKey&&i=e(i).offset().top+n.topOffset&&t 6 |
7 |
8 |
9 |

About S'BOTS

10 |

11 | The creators of one of the largest crypto currencies on the planet, Solana (SOL) are from Solana Beach, California. Solana Beach Bot is a tribute to the town where SOL started. Solana Beach is also where our offices are and where the creator of Solana Beach Bots has lived for the last 20 years. The Solana Beach Bots encompass what it means to live in Solana Beach: chill, free-spirited, and most of all, FUN! 12 |

13 |
14 |
15 |
16 |
17 |
S'BOTS
18 |
19 |
20 |
21 |
22 | 23 | ) 24 | } 25 | 26 | export default About -------------------------------------------------------------------------------- /src/utils/mx/utils/createPipelineExecutor.ts: -------------------------------------------------------------------------------- 1 | export async function createPipelineExecutor( 2 | data: IterableIterator, 3 | executor: (d: T) => void, 4 | { 5 | delay = 0, 6 | jobsCount = 1, 7 | sequence = 1, 8 | }: { 9 | delay?: number; 10 | jobsCount?: number; 11 | sequence?: number; 12 | } = {}, 13 | ) { 14 | function execute(iter: IteratorResult) { 15 | executor(iter.value); 16 | } 17 | 18 | async function next() { 19 | if (sequence <= 1) { 20 | const iter = data.next(); 21 | if (iter.done) { 22 | return; 23 | } 24 | await execute(iter); 25 | } else { 26 | const promises: any[] = []; 27 | let isDone = false; 28 | for (let i = 0; i < sequence; i++) { 29 | const iter = data.next(); 30 | if (!iter.done) { 31 | promises.push(execute(iter)); 32 | } else { 33 | isDone = true; 34 | break; 35 | } 36 | } 37 | await Promise.all(promises); 38 | if (isDone) { 39 | return; 40 | } 41 | } 42 | if (delay > 0) { 43 | await new Promise(resolve => setTimeout(resolve, delay)); 44 | } else { 45 | await Promise.resolve(); 46 | } 47 | await next(); 48 | } 49 | const result = new Array>(jobsCount); 50 | for (let i = 0; i < jobsCount; i++) { 51 | result[i] = next(); 52 | } 53 | await Promise.all(result); 54 | } 55 | -------------------------------------------------------------------------------- /public/js/YouTubePopUp.js: -------------------------------------------------------------------------------- 1 | ! function(o) { 2 | o.fn.YouTubePopUp = function(e) { 3 | var u = o.extend({ autoplay: 1 }, e); 4 | o(this).on("click", function(e) { 5 | var a = o(this).attr("href"); 6 | if (a.match(/(youtube.com)/)) var p = "v=", 7 | t = 1; 8 | if (a.match(/(youtu.be)/) || a.match(/(vimeo.com\/)+[0-9]/)) p = "/", t = 3; 9 | if (a.match(/(vimeo.com\/)+[a-zA-Z]/)) p = "/", t = 5; 10 | var i = a.split(p)[t].replace(/(&)+(.*)/, ""); 11 | if (a.match(/(youtu.be)/) || a.match(/(youtube.com)/)) var c = "https://www.youtube.com/embed/" + i + "?autoplay=" + u.autoplay; 12 | if (a.match(/(vimeo.com\/)+[0-9]/) || a.match(/(vimeo.com\/)+[a-zA-Z]/)) c = "https://player.vimeo.com/video/" + i + "?autoplay=" + u.autoplay; 13 | o("body").append('
'), o(".YouTubePopUp-Wrap").hasClass("YouTubePopUp-animation") && setTimeout(function() { o(".YouTubePopUp-Wrap").removeClass("YouTubePopUp-animation") }, 600), o(".YouTubePopUp-Wrap, .YouTubePopUp-Close").click(function() { o(".YouTubePopUp-Wrap").addClass("YouTubePopUp-Hide").delay(515).queue(function() { o(this).remove() }) }), e.preventDefault() 14 | }), o(document).keyup(function(e) { 27 == e.keyCode && o(".YouTubePopUp-Wrap, .YouTubePopUp-Close").click() }) 15 | } 16 | }(jQuery); -------------------------------------------------------------------------------- /src/utils/mx/utils/programIds.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from '@solana/web3.js'; 2 | import { findProgramAddress } from '../utils'; 3 | 4 | import { 5 | METADATA_PROGRAM_ID, 6 | TOKEN_PROGRAM_ID, 7 | SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID, 8 | METAPLEX_ID, 9 | BPF_UPGRADE_LOADER_ID, 10 | SYSTEM, 11 | MEMO_ID, 12 | VAULT_ID, 13 | AUCTION_ID, 14 | toPublicKey, 15 | } from './ids'; 16 | 17 | // export const getStoreID = async (storeOwnerAddress?: string) => { 18 | // if (!storeOwnerAddress) { 19 | // return undefined; 20 | // } 21 | 22 | // console.log('Store owner', storeOwnerAddress, METAPLEX_ID); 23 | // const programs = await findProgramAddress( 24 | // [ 25 | // Buffer.from('metaplex'), 26 | // toPublicKey(METAPLEX_ID).toBuffer(), 27 | // toPublicKey(storeOwnerAddress).toBuffer(), 28 | // ], 29 | // toPublicKey(METAPLEX_ID), 30 | // ); 31 | // const storeAddress = programs[0]; 32 | 33 | // return storeAddress; 34 | // }; 35 | 36 | export const setProgramIds = async (store?: string) => { 37 | STORE = store ? toPublicKey(store) : undefined; 38 | }; 39 | 40 | let STORE: PublicKey | undefined; 41 | 42 | export const programIds = () => { 43 | return { 44 | token: TOKEN_PROGRAM_ID, 45 | associatedToken: SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID, 46 | bpf_upgrade_loader: BPF_UPGRADE_LOADER_ID, 47 | system: SYSTEM, 48 | metadata: METADATA_PROGRAM_ID, 49 | memo: MEMO_ID, 50 | vault: VAULT_ID, 51 | auction: AUCTION_ID, 52 | metaplex: METAPLEX_ID, 53 | store: STORE, 54 | }; 55 | }; 56 | -------------------------------------------------------------------------------- /public/css/plugins/YouTubePopUp.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";.YouTubePopUp-Wrap{position:fixed;width:100%;height:100%;background-color:#000;background-color:rgba(0,0,0,.8);top:0;left:0;z-index:9999999999999}.YouTubePopUp-animation{opacity:0;-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:YouTubePopUp;animation-name:YouTubePopUp}@-webkit-keyframes YouTubePopUp{0%{opacity:0}100%{opacity:1}}@keyframes YouTubePopUp{0%{opacity:0}100%{opacity:1}}body.logged-in .YouTubePopUp-Wrap{top:32px;z-index:99998}.YouTubePopUp-Content{max-width:680px;display:block;margin:0 auto;height:100%;position:relative}.YouTubePopUp-Content iframe{max-width:100%!important;width:100%!important;display:block!important;height:480px!important;border:none!important;position:absolute;top:0;bottom:0;margin:auto 0}.YouTubePopUp-Hide{-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:YouTubePopUpHide;animation-name:YouTubePopUpHide}@-webkit-keyframes YouTubePopUpHide{0%{opacity:1}100%{opacity:0}}@keyframes YouTubePopUpHide{0%{opacity:1}100%{opacity:0}}.YouTubePopUp-Close{position:absolute;top:0;cursor:pointer;bottom:528px;right:0;margin:auto 0;width:24px;height:24px;background:url(close.png) no-repeat;background-size:24px 24px;-webkit-background-size:24px 24px;-moz-background-size:24px 24px;-o-background-size:24px 24px}.YouTubePopUp-Close:hover{opacity:.5}@media all and (max-width:768px) and (min-width:10px){.YouTubePopUp-Content{max-width:90%}}@media all and (max-width:600px) and (min-width:10px){.YouTubePopUp-Content iframe{height:320px!important}.YouTubePopUp-Close{bottom:362px}}@media all and (max-width:480px) and (min-width:10px){.YouTubePopUp-Content iframe{height:220px!important}.YouTubePopUp-Close{bottom:262px}} -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import {useMemo} from 'react'; 2 | import VideoBG from './components/VideoBG'; 3 | import Slider from './components/Slider'; 4 | import About from './components/About'; 5 | import Pro from './components/Pro'; 6 | import TimeLine from './components/TimeLine'; 7 | import Faq from './components/Faq'; 8 | 9 | import { clusterApiUrl } from '@solana/web3.js'; 10 | 11 | import { 12 | ConnectionProvider, 13 | WalletProvider, 14 | } from "@solana/wallet-adapter-react/lib/index.js"; 15 | 16 | import { 17 | getPhantomWallet, 18 | getSlopeWallet, 19 | getSolflareWallet, 20 | getLedgerWallet, 21 | getSolletWallet, 22 | getSolletExtensionWallet 23 | } from '@solana/wallet-adapter-wallets'; 24 | 25 | import { 26 | WalletModalProvider, 27 | } from "@solana/wallet-adapter-react-ui"; 28 | import { WalletAdapterNetwork } from '@solana/wallet-adapter-base/lib/adapter'; 29 | 30 | 31 | /*This is main app.*/ 32 | function App() { 33 | const network = clusterApiUrl('devnet'); 34 | const wallets = useMemo(() => [ 35 | getPhantomWallet(), 36 | getSolletWallet({network}), 37 | getSolflareWallet(), 38 | getSolletExtensionWallet({network}), 39 | getLedgerWallet(), 40 | getSlopeWallet(), 41 | ], [network]); 42 | 43 | return ( 44 |
45 | 46 | 47 | 48 | 49 | 50 |
51 | 52 | 53 | 54 | 55 |
56 |
57 |
58 |
59 |
60 | ); 61 | } 62 | 63 | export default App; 64 | -------------------------------------------------------------------------------- /src/utils/mx/contexts/accounts/parsesrs.ts: -------------------------------------------------------------------------------- 1 | import { AccountInfo } from '@solana/web3.js'; 2 | import { TokenAccount } from '../../models'; 3 | // import { ParsedAccountBase } from './types'; 4 | import { deserializeMint, deserializeAccount } from './deserialize'; 5 | import { StringPublicKey } from '../../utils'; 6 | 7 | // export const MintParser = ( 8 | // pubKey: StringPublicKey, 9 | // info: AccountInfo, 10 | // ) => { 11 | // const buffer = Buffer.from(info.data); 12 | 13 | // const data = deserializeMint(buffer); 14 | 15 | // const details = { 16 | // pubkey: pubKey, 17 | // account: { 18 | // ...info, 19 | // }, 20 | // info: data, 21 | // } as ParsedAccountBase; 22 | 23 | // return details; 24 | // }; 25 | 26 | export const TokenAccountParser = ( 27 | pubKey: StringPublicKey, 28 | info: AccountInfo, 29 | ) => { 30 | // Sometimes a wrapped sol account gets closed, goes to 0 length, 31 | // triggers an update over wss which triggers this guy to get called 32 | // since your UI already logged that pubkey as a token account. Check for length. 33 | if (info.data.length > 0) { 34 | const buffer = Buffer.from(info.data); 35 | const data = deserializeAccount(buffer); 36 | 37 | const details = { 38 | pubkey: pubKey, 39 | account: { 40 | ...info, 41 | }, 42 | info: data, 43 | } as TokenAccount; 44 | 45 | return details; 46 | } 47 | }; 48 | 49 | // export const GenericAccountParser = ( 50 | // pubKey: StringPublicKey, 51 | // info: AccountInfo, 52 | // ) => { 53 | // const buffer = Buffer.from(info.data); 54 | 55 | // const details = { 56 | // pubkey: pubKey, 57 | // account: { 58 | // ...info, 59 | // }, 60 | // info: buffer, 61 | // } as ParsedAccountBase; 62 | 63 | // return details; 64 | // }; 65 | -------------------------------------------------------------------------------- /src/utils/mx/utils/eventEmitter.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter as Emitter } from 'eventemitter3'; 2 | 3 | export class CacheUpdateEvent { 4 | static type = 'CacheUpdate'; 5 | id: string; 6 | parser: any; 7 | isNew: boolean; 8 | isActive: boolean; 9 | constructor(id: string, isNew: boolean, parser: any, isActive: boolean) { 10 | this.id = id; 11 | this.parser = parser; 12 | this.isNew = isNew; 13 | this.isActive = isActive; 14 | } 15 | } 16 | 17 | export class CacheDeleteEvent { 18 | static type = 'CacheUpdate'; 19 | id: string; 20 | constructor(id: string) { 21 | this.id = id; 22 | } 23 | } 24 | 25 | export class MarketUpdateEvent { 26 | static type = 'MarketUpdate'; 27 | ids: Set; 28 | constructor(ids: Set) { 29 | this.ids = ids; 30 | } 31 | } 32 | 33 | export class EventEmitter { 34 | private emitter = new Emitter(); 35 | 36 | onMarket(callback: (args: MarketUpdateEvent) => void) { 37 | this.emitter.on(MarketUpdateEvent.type, callback); 38 | 39 | return () => this.emitter.removeListener(MarketUpdateEvent.type, callback); 40 | } 41 | 42 | onCache(callback: (args: CacheUpdateEvent) => void) { 43 | this.emitter.on(CacheUpdateEvent.type, callback); 44 | 45 | return () => this.emitter.removeListener(CacheUpdateEvent.type, callback); 46 | } 47 | 48 | raiseMarketUpdated(ids: Set) { 49 | this.emitter.emit(MarketUpdateEvent.type, new MarketUpdateEvent(ids)); 50 | } 51 | 52 | raiseCacheUpdated( 53 | id: string, 54 | isNew: boolean, 55 | parser: any, 56 | isActive: boolean, 57 | ) { 58 | this.emitter.emit( 59 | CacheUpdateEvent.type, 60 | new CacheUpdateEvent(id, isNew, parser, isActive), 61 | ); 62 | } 63 | 64 | raiseCacheDeleted(id: string) { 65 | this.emitter.emit(CacheDeleteEvent.type, new CacheDeleteEvent(id)); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "SolanaBeachBot", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@nfteyez/sol-rayz": "^0.8.2", 7 | "@solana/spl-token": "^0.1.8", 8 | "@solana/spl-token-registry": "^0.2.517", 9 | "@solana/wallet-adapter-base": "^0.7.0", 10 | "@solana/wallet-adapter-react": "^0.13.1", 11 | "@solana/wallet-adapter-react-ui": "^0.6.1", 12 | "@solana/wallet-adapter-wallets": "^0.11.3", 13 | "@solana/web3.js": "^1.31.0", 14 | "@testing-library/jest-dom": "^5.11.4", 15 | "@testing-library/react": "^11.1.0", 16 | "@testing-library/user-event": "^12.1.10", 17 | "@types/jest": "^27.4.0", 18 | "@types/moment": "^2.13.0", 19 | "@types/node": "^17.0.8", 20 | "@types/react": "^17.0.38", 21 | "@types/react-dom": "^17.0.11", 22 | "@types/react-toastify": "^4.1.0", 23 | "aos": "^2.3.4", 24 | "axios": "^0.21.1", 25 | "bn": "^1.0.5", 26 | "bootstrap": "^5.1.0", 27 | "bs58": "^4.0.1", 28 | "buffer-layout": "^1.2.2", 29 | "envfile": "^6.17.0", 30 | "ethers": "^5.4.5", 31 | "font-awesome": "^4.7.0", 32 | "fs": "0.0.1-security", 33 | "papaparse": "^5.3.1", 34 | "react": "^17.0.2", 35 | "react-dom": "^17.0.2", 36 | "react-hot-toast": "^2.2.0", 37 | "react-router-dom": "^5.3.0", 38 | "react-scripts": "4.0.3", 39 | "react-toastify": "^8.0.3", 40 | "swiper": "^7.2.0", 41 | "theme-ui": "^0.10.0", 42 | "typescript": "^4.5.4", 43 | "web-vitals": "^1.0.1", 44 | "web3": "^1.5.2" 45 | }, 46 | "scripts": { 47 | "start": "react-scripts start", 48 | "build": "react-scripts build", 49 | "test": "react-scripts test", 50 | "eject": "react-scripts eject" 51 | }, 52 | "eslintConfig": { 53 | "extends": [ 54 | "react-app", 55 | "react-app/jest" 56 | ] 57 | }, 58 | "browserslist": { 59 | "production": [ 60 | ">0.2%", 61 | "not dead", 62 | "not op_mini all" 63 | ], 64 | "development": [ 65 | "last 1 chrome version", 66 | "last 1 firefox version", 67 | "last 1 safari version" 68 | ] 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/utils/mx/contexts/accounts/deserialize.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from '@solana/web3.js'; 2 | import { AccountLayout, MintInfo, MintLayout, u64 } from '@solana/spl-token'; 3 | 4 | // TODO: expose in spl package 5 | export const deserializeAccount = (data: Buffer) => { 6 | const accountInfo = AccountLayout.decode(data); 7 | accountInfo.mint = new PublicKey(accountInfo.mint); 8 | accountInfo.owner = new PublicKey(accountInfo.owner); 9 | accountInfo.amount = u64.fromBuffer(accountInfo.amount); 10 | 11 | if (accountInfo.delegateOption === 0) { 12 | accountInfo.delegate = null; 13 | accountInfo.delegatedAmount = new u64(0); 14 | } else { 15 | accountInfo.delegate = new PublicKey(accountInfo.delegate); 16 | accountInfo.delegatedAmount = u64.fromBuffer(accountInfo.delegatedAmount); 17 | } 18 | 19 | accountInfo.isInitialized = accountInfo.state !== 0; 20 | accountInfo.isFrozen = accountInfo.state === 2; 21 | 22 | if (accountInfo.isNativeOption === 1) { 23 | accountInfo.rentExemptReserve = u64.fromBuffer(accountInfo.isNative); 24 | accountInfo.isNative = true; 25 | } else { 26 | accountInfo.rentExemptReserve = null; 27 | accountInfo.isNative = false; 28 | } 29 | 30 | if (accountInfo.closeAuthorityOption === 0) { 31 | accountInfo.closeAuthority = null; 32 | } else { 33 | accountInfo.closeAuthority = new PublicKey(accountInfo.closeAuthority); 34 | } 35 | 36 | return accountInfo; 37 | }; 38 | 39 | // TODO: expose in spl package 40 | export const deserializeMint = (data: Buffer) => { 41 | if (data.length !== MintLayout.span) { 42 | throw new Error('Not a valid Mint'); 43 | } 44 | 45 | const mintInfo = MintLayout.decode(data); 46 | 47 | if (mintInfo.mintAuthorityOption === 0) { 48 | mintInfo.mintAuthority = null; 49 | } else { 50 | mintInfo.mintAuthority = new PublicKey(mintInfo.mintAuthority); 51 | } 52 | 53 | mintInfo.supply = u64.fromBuffer(mintInfo.supply); 54 | mintInfo.isInitialized = mintInfo.isInitialized !== 0; 55 | 56 | if (mintInfo.freezeAuthorityOption === 0) { 57 | mintInfo.freezeAuthority = null; 58 | } else { 59 | mintInfo.freezeAuthority = new PublicKey(mintInfo.freezeAuthority); 60 | } 61 | 62 | return mintInfo as MintInfo; 63 | }; 64 | -------------------------------------------------------------------------------- /src/utils/mx/utils/assets.ts: -------------------------------------------------------------------------------- 1 | import { UseLocalStorage } from './useLocalStorage'; 2 | import { TokenInfo } from '@solana/spl-token-registry'; 3 | 4 | export const LAMPORT_MULTIPLIER = 10 ** 9; 5 | const WINSTON_MULTIPLIER = 10 ** 12; 6 | 7 | export const filterModalSolTokens = (tokens: TokenInfo[]) => { 8 | return tokens; 9 | }; 10 | 11 | export async function getAssetCostToStore(files: File[]) { 12 | const localStorage = UseLocalStorage(); 13 | const totalBytes = files.reduce((sum, f) => (sum += f.size), 0); 14 | console.log('Total bytes', totalBytes); 15 | const txnFeeInWinstons = parseInt( 16 | await (await fetch('https://arweave.net/price/0')).text(), 17 | ); 18 | console.log('txn fee', txnFeeInWinstons); 19 | const byteCostInWinstons = parseInt( 20 | await ( 21 | await fetch('https://arweave.net/price/' + totalBytes.toString()) 22 | ).text(), 23 | ); 24 | console.log('byte cost', byteCostInWinstons); 25 | const totalArCost = 26 | (txnFeeInWinstons * files.length + byteCostInWinstons) / WINSTON_MULTIPLIER; 27 | 28 | console.log('total ar', totalArCost); 29 | 30 | let conversionRates = JSON.parse( 31 | localStorage.getItem('conversionRates') || '{}', 32 | ); 33 | 34 | if ( 35 | !conversionRates || 36 | !conversionRates.expiry || 37 | conversionRates.expiry < Date.now() 38 | ) { 39 | console.log('Calling conversion rate'); 40 | conversionRates = { 41 | value: JSON.parse( 42 | await ( 43 | await fetch( 44 | 'https://api.coingecko.com/api/v3/simple/price?ids=solana,arweave&vs_currencies=usd', 45 | ) 46 | ).text(), 47 | ), 48 | expiry: Date.now() + 5 * 60 * 1000, 49 | }; 50 | 51 | if (conversionRates.value.solana) { 52 | try { 53 | localStorage.setItem( 54 | 'conversionRates', 55 | JSON.stringify(conversionRates), 56 | ); 57 | } catch { 58 | // ignore 59 | } 60 | } 61 | } 62 | 63 | // To figure out how many lamports are required, multiply ar byte cost by this number 64 | const arMultiplier = 65 | conversionRates.value.arweave.usd / conversionRates.value.solana.usd; 66 | console.log('Ar mult', arMultiplier); 67 | // We also always make a manifest file, which, though tiny, needs payment. 68 | return LAMPORT_MULTIPLIER * totalArCost * arMultiplier * 1.1; 69 | } 70 | -------------------------------------------------------------------------------- /src/utils/mx/utils/strings.ts: -------------------------------------------------------------------------------- 1 | // credit https://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array 2 | export function toUTF8Array(str: string) { 3 | const utf8: number[] = []; 4 | for (let i = 0; i < str.length; i++) { 5 | let charcode = str.charCodeAt(i); 6 | if (charcode < 0x80) utf8.push(charcode); 7 | else if (charcode < 0x800) { 8 | utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f)); 9 | } else if (charcode < 0xd800 || charcode >= 0xe000) { 10 | utf8.push( 11 | 0xe0 | (charcode >> 12), 12 | 0x80 | ((charcode >> 6) & 0x3f), 13 | 0x80 | (charcode & 0x3f), 14 | ); 15 | } 16 | // surrogate pair 17 | else { 18 | i++; 19 | // UTF-16 encodes 0x10000-0x10FFFF by 20 | // subtracting 0x10000 and splitting the 21 | // 20 bits of 0x0-0xFFFFF into two halves 22 | charcode = 23 | 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff)); 24 | utf8.push( 25 | 0xf0 | (charcode >> 18), 26 | 0x80 | ((charcode >> 12) & 0x3f), 27 | 0x80 | ((charcode >> 6) & 0x3f), 28 | 0x80 | (charcode & 0x3f), 29 | ); 30 | } 31 | } 32 | return utf8; 33 | } 34 | 35 | //courtesy https://gist.github.com/joni/3760795 36 | export function fromUTF8Array(data: number[]) { 37 | // array of bytes 38 | let str = '', 39 | i; 40 | 41 | for (i = 0; i < data.length; i++) { 42 | const value = data[i]; 43 | 44 | if (value < 0x80) { 45 | str += String.fromCharCode(value); 46 | } else if (value > 0xbf && value < 0xe0) { 47 | str += String.fromCharCode(((value & 0x1f) << 6) | (data[i + 1] & 0x3f)); 48 | i += 1; 49 | } else if (value > 0xdf && value < 0xf0) { 50 | str += String.fromCharCode( 51 | ((value & 0x0f) << 12) | 52 | ((data[i + 1] & 0x3f) << 6) | 53 | (data[i + 2] & 0x3f), 54 | ); 55 | i += 2; 56 | } else { 57 | // surrogate pair 58 | const charCode = 59 | (((value & 0x07) << 18) | 60 | ((data[i + 1] & 0x3f) << 12) | 61 | ((data[i + 2] & 0x3f) << 6) | 62 | (data[i + 3] & 0x3f)) - 63 | 0x010000; 64 | 65 | str += String.fromCharCode( 66 | (charCode >> 10) | 0xd800, 67 | (charCode & 0x03ff) | 0xdc00, 68 | ); 69 | i += 3; 70 | } 71 | } 72 | 73 | return str; 74 | } 75 | -------------------------------------------------------------------------------- /src/utils/mx/utils/ids.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey, AccountInfo } from '@solana/web3.js'; 2 | 3 | export type StringPublicKey = string; 4 | 5 | export class LazyAccountInfoProxy { 6 | executable: boolean = false; 7 | owner: StringPublicKey = ''; 8 | lamports: number = 0; 9 | 10 | get data() { 11 | // 12 | return undefined as unknown as T; 13 | } 14 | } 15 | 16 | export interface LazyAccountInfo { 17 | executable: boolean; 18 | owner: StringPublicKey; 19 | lamports: number; 20 | data: [string, string]; 21 | } 22 | 23 | const PubKeysInternedMap = new Map(); 24 | 25 | export const toPublicKey = (key: string | PublicKey) => { 26 | if (typeof key !== 'string') { 27 | return key; 28 | } 29 | 30 | let result = PubKeysInternedMap.get(key); 31 | if (!result) { 32 | result = new PublicKey(key); 33 | PubKeysInternedMap.set(key, result); 34 | } 35 | 36 | return result; 37 | }; 38 | 39 | export const pubkeyToString = (key: PublicKey | null | string = '') => { 40 | return typeof key === 'string' ? key : key?.toBase58() || ''; 41 | }; 42 | 43 | export interface PublicKeyStringAndAccount { 44 | pubkey: string; 45 | account: AccountInfo; 46 | } 47 | 48 | export const WRAPPED_SOL_MINT = new PublicKey( 49 | 'So11111111111111111111111111111111111111112', 50 | ); 51 | 52 | export const TOKEN_PROGRAM_ID = new PublicKey( 53 | 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', 54 | ); 55 | 56 | export const SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID = new PublicKey( 57 | 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', 58 | ); 59 | 60 | export const BPF_UPGRADE_LOADER_ID = new PublicKey( 61 | 'BPFLoaderUpgradeab1e11111111111111111111111', 62 | ); 63 | 64 | export const MEMO_ID = new PublicKey( 65 | 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr', 66 | ); 67 | 68 | export const METADATA_PROGRAM_ID = 69 | 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s' as StringPublicKey; 70 | 71 | export const VAULT_ID = 72 | 'vau1zxA2LbssAUEF7Gpw91zMM1LvXrvpzJtmZ58rPsn' as StringPublicKey; 73 | 74 | export const AUCTION_ID = 75 | 'auctxRXPeJoc4817jDhf4HbjnhEcr1cCXenosMhK5R8' as StringPublicKey; 76 | 77 | export const METAPLEX_ID = 78 | 'p1exdMJcjVao65QdewkaZRUnU6VPSXhus9n2GzWfh98' as StringPublicKey; 79 | 80 | export const SYSTEM = new PublicKey('11111111111111111111111111111111'); 81 | 82 | export const AR_SOL_HOLDER_ID = new PublicKey( 83 | 'HvwC9QSAzvGXhhVrgPmauVwFWcYZhne3hVot9EbHuFTm', 84 | ); 85 | -------------------------------------------------------------------------------- /src/utils/mx/models/account.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AccountInfo, 3 | Keypair, 4 | PublicKey, 5 | TransactionInstruction, 6 | } from '@solana/web3.js'; 7 | 8 | import { AccountInfo as TokenAccountInfo, Token } from '@solana/spl-token'; 9 | import { TOKEN_PROGRAM_ID } from '../utils/ids'; 10 | import BufferLayout from 'buffer-layout'; 11 | 12 | export interface TokenAccount { 13 | pubkey: string; 14 | account: AccountInfo; 15 | info: TokenAccountInfo; 16 | } 17 | 18 | export interface ParsedDataAccount { 19 | amount: number; 20 | rawAmount: string; 21 | parsedAssetAddress: string; 22 | parsedAccount: any; 23 | assetDecimals: number; 24 | assetIcon: any; 25 | name: string; 26 | symbol: string; 27 | sourceAddress: string; 28 | targetAddress: string; 29 | } 30 | 31 | export const ParsedDataLayout = BufferLayout.struct([ 32 | BufferLayout.blob(32, 'amount'), 33 | BufferLayout.u8('toChain'), 34 | BufferLayout.blob(32, 'sourceAddress'), 35 | BufferLayout.blob(32, 'targetAddress'), 36 | BufferLayout.blob(32, 'assetAddress'), 37 | BufferLayout.u8('assetChain'), 38 | BufferLayout.u8('assetDecimals'), 39 | BufferLayout.seq(BufferLayout.u8(), 1), // 4 byte alignment because a u32 is following 40 | BufferLayout.u32('nonce'), 41 | BufferLayout.blob(1001, 'vaa'), 42 | BufferLayout.seq(BufferLayout.u8(), 3), // 4 byte alignment because a u32 is following 43 | BufferLayout.u32('vaaTime'), 44 | BufferLayout.u32('lockupTime'), 45 | BufferLayout.u8('pokeCounter'), 46 | BufferLayout.blob(32, 'signatureAccount'), 47 | BufferLayout.u8('initialized'), 48 | ]); 49 | 50 | export function approve( 51 | instructions: TransactionInstruction[], 52 | cleanupInstructions: TransactionInstruction[], 53 | account: PublicKey, 54 | owner: PublicKey, 55 | amount: number, 56 | autoRevoke = true, 57 | 58 | // if delegate is not passed ephemeral transfer authority is used 59 | delegate?: PublicKey, 60 | existingTransferAuthority?: Keypair, 61 | ): Keypair { 62 | const tokenProgram = TOKEN_PROGRAM_ID; 63 | 64 | const transferAuthority = existingTransferAuthority || Keypair.generate(); 65 | //const delegateKey = delegate ?? transferAuthority.publicKey; 66 | 67 | instructions.push( 68 | Token.createApproveInstruction( 69 | tokenProgram, 70 | account, 71 | delegate ?? transferAuthority.publicKey, 72 | owner, 73 | [], 74 | amount, 75 | ), 76 | ); 77 | 78 | if (autoRevoke) { 79 | cleanupInstructions.push( 80 | Token.createRevokeInstruction(tokenProgram, account, owner, []), 81 | ); 82 | } 83 | 84 | return transferAuthority; 85 | } 86 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 19 | 20 | 29 | Solana Beach Bots 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /public/css/plugins/owl.carousel.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Owl Carousel v2.2.0 3 | * Copyright 2013-2016 David Deutsch 4 | * Licensed under MIT (https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE) 5 | */ 6 | .owl-carousel,.owl-carousel .owl-item{-webkit-tap-highlight-color:transparent;position:relative}.owl-carousel{display:none;width:100%;z-index:1}.owl-carousel .owl-stage{position:relative;-ms-touch-action:pan-Y}.owl-carousel .owl-stage:after{content:".";display:block;clear:both;visibility:hidden;line-height:0;height:0}.owl-carousel .owl-stage-outer{position:relative;overflow:hidden;-webkit-transform:translate3d(0,0,0)}.owl-carousel .owl-item,.owl-carousel .owl-wrapper{-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0)}.owl-carousel .owl-item{min-height:1px;float:left;-webkit-backface-visibility:hidden;-webkit-touch-callout:none}.owl-carousel .owl-item img{display:block;width:100%}.owl-carousel .owl-dots.disabled,.owl-carousel .owl-nav.disabled{display:none}.no-js .owl-carousel,.owl-carousel.owl-loaded{display:block}.owl-carousel .owl-dot,.owl-carousel .owl-nav .owl-next,.owl-carousel .owl-nav .owl-prev{cursor:pointer;cursor:hand;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.owl-carousel.owl-loading{opacity:0;display:block}.owl-carousel.owl-hidden{opacity:0}.owl-carousel.owl-refresh .owl-item{visibility:hidden}.owl-carousel.owl-drag .owl-item{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}.owl-carousel.owl-grab{cursor:move;cursor:grab}.owl-carousel.owl-rtl{direction:rtl}.owl-carousel.owl-rtl .owl-item{float:right}.owl-carousel .animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.owl-carousel .owl-animated-in{z-index:0}.owl-carousel .owl-animated-out{z-index:1}.owl-carousel .fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.owl-height{transition:height .5s ease-in-out}.owl-carousel .owl-item .owl-lazy{opacity:0;transition:opacity .4s ease}.owl-carousel .owl-item img.owl-lazy{-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.owl-carousel .owl-video-wrapper{position:relative;height:100%;background:#000}.owl-carousel .owl-video-play-icon{position:absolute;height:80px;width:80px;left:50%;top:50%;margin-left:-40px;margin-top:-40px;background:url("../../../../../../../www.duruthemes.com/idesign/Roboto-v3/css/plugins/owl.video.play.html") no-repeat;cursor:pointer;z-index:1;-webkit-backface-visibility:hidden;transition:-webkit-transform .1s ease;transition:transform .1s ease}.owl-carousel .owl-video-play-icon:hover{-webkit-transform:scale(1.3,1.3);-ms-transform:scale(1.3,1.3);transform:scale(1.3,1.3)}.owl-carousel .owl-video-playing .owl-video-play-icon,.owl-carousel .owl-video-playing .owl-video-tn{display:none}.owl-carousel .owl-video-tn{opacity:0;height:100%;background-position:center center;background-repeat:no-repeat;background-size:contain;transition:opacity .4s ease}.owl-carousel .owl-video-frame{position:relative;z-index:1;height:100%;width:100%} -------------------------------------------------------------------------------- /public/js/custom.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | "use strict"; 3 | var e = $(window); 4 | $.scrollIt({ 5 | upKey: 38, 6 | downKey: 40, 7 | easing: "swing", 8 | scrollTime: 600, 9 | activeClass: "active", 10 | onPageChange: null, 11 | topOffset: -70 12 | }), e.on("scroll", function () { 13 | var a = e.scrollTop(), 14 | t = $(".navbar"), 15 | r = $(".mobileMenu"), 16 | n = $(".navbar .logo> img"); 17 | a > 100 ? (t.addClass("nav-scroll"), n.attr("src", "img/logo.png")) : (t.removeClass("nav-scroll"), n.attr("src", "img/logo.png")) 18 | a > 100 ? r.addClass("mobileMenuShow ") : (r.removeClass("mobileMenuShow ")) 19 | }), $(".navbar-nav .dropdown-item a").on("click", function () { 20 | $(".navbar-collapse").removeClass("show") 21 | }); 22 | var a = $(".bg-img, section"); 23 | a.each(function (e) { 24 | $(this).attr("data-background") && $(this).css("background-image", "url(" + $(this).data("background") + ")") 25 | }) 26 | var t = function () { 27 | $(".animate-box").waypoint(function (e) { 28 | "down" !== e || $(this.element).hasClass("animated") || (0, $(this.element).addClass("item-animate"), setTimeout(function () { 29 | $("body .animate-box.item-animate").each(function (e) { 30 | var a = $(this); 31 | setTimeout(function () { 32 | var e = a.data("animate-effect"); 33 | "fadeIn" === e ? a.addClass("fadeIn animated") : "fadeInLeft" === e ? a.addClass("fadeInLeft animated") : "fadeInRight" === e ? a.addClass("fadeInRight animated") : a.addClass("fadeInUp animated"), a.removeClass("item-animate") 34 | }, 200 * e, "easeInOutExpo") 35 | }) 36 | }, 100)) 37 | }, { 38 | offset: "85%" 39 | }) 40 | }; 41 | $(function () { 42 | t() 43 | }), $(".img-zoom").magnificPopup({ 44 | type: "image", 45 | closeOnContentClick: !0, 46 | mainClass: "mfp-fade", 47 | gallery: { 48 | enabled: !0, 49 | navigateByImgClick: !0, 50 | preload: [0, 1] 51 | } 52 | }), $(".magnific-youtube, .magnific-vimeo, .magnific-custom").magnificPopup({ 53 | disableOn: 700, 54 | type: "iframe", 55 | mainClass: "mfp-fade", 56 | removalDelay: 300, 57 | preloader: !1, 58 | fixedContentPos: !1 59 | }); 60 | var s = 150, 61 | l = 550; 62 | jQuery(window).on("scroll", function () { 63 | jQuery(this).scrollTop() > s ? jQuery(".progress-wrap").addClass("active-progress") : jQuery(".progress-wrap").removeClass("active-progress") 64 | }), jQuery(".progress-wrap").on("click", function (e) { 65 | return e.preventDefault(), jQuery("html, body").animate({ 66 | scrollTop: 0 67 | }, l), !1 68 | }) 69 | }), $(".accordion-box").length && $(".accordion-box").on("click", ".acc-btn", function () { 70 | var e = $(this).parents(".accordion-box"), 71 | a = $(this).parents(".accordion"); 72 | $(this).next(".acc-content").is(":visible") ? ($(this).removeClass("active"), $(this).next(".acc-content").slideUp(300), $(e).children(".accordion").removeClass("active-block")) : ($(e).find(".accordion .acc-btn").removeClass("active"), $(this).addClass("active"), $(e).children(".accordion").removeClass("active-block"), $(e).find(".accordion").children(".acc-content").slideUp(300), a.addClass("active-block"), $(this).next(".acc-content").slideDown(300)) 73 | }), paceOptions = { 74 | ajax: !0, 75 | document: !0, 76 | eventLag: !1 77 | }, Pace.on("done", function () { 78 | $("#preloader").delay(500).fadeOut(800) 79 | }), jQuery; -------------------------------------------------------------------------------- /src/components/Pro/index.js: -------------------------------------------------------------------------------- 1 | import jp from '../../img/Jp.png' 2 | import jonathan from '../../img/Jonathan.png' 3 | import paulina from '../../img/Paulina.png' 4 | import savana from '../../img/Savana.png' 5 | import sophia from '../../img/Sophia.png' 6 | import chris from '../../img/Chris.png' 7 | 8 | function Pro() { 9 | return ( 10 |
11 |
12 |

Meet Our S'BOTS Team

13 |

14 | Solana Beach Bots were created in Solana Beach by a few techies who wanted to create something cool. 15 |

16 |
17 |
18 |
19 |
20 |
JP: BINGE WATCHES FRESH-PRINCE OF BEL-AIR
21 |
22 |
23 |
24 |
25 |
26 |
JONATHAN: If it's not fuschia I don't want it
27 |
28 |
29 |
30 |
31 |
32 |
Savana: Purrfessional multitasker
33 |
34 |
35 |
36 |
37 |
38 |
Paulina: LOL addict
39 |
40 |
41 |
42 |
43 |
44 |
Chris: strong coffee and movies
45 |
46 |
47 |
48 |
49 |
50 |
Sophia: Eats pickles in free time
51 |
52 |
53 |
54 |
55 |
56 | ) 57 | } 58 | 59 | export default Pro -------------------------------------------------------------------------------- /src/components/ComingSoon/index.js: -------------------------------------------------------------------------------- 1 | import {useEffect} from 'react' 2 | 3 | function ComingSoon() { 4 | useEffect(() => { 5 | const interval = setInterval(() => { 6 | countdown() 7 | }, 1000) 8 | return () => clearInterval(interval); 9 | }) 10 | 11 | const countdown = () => { 12 | var now = new Date(); 13 | var eventDate = new Date(2021, 11, 10); 14 | var currentTiime = now.getTime(); 15 | var eventTime = eventDate.getTime(); 16 | var remTime = eventTime - currentTiime; 17 | var s = Math.floor(remTime / 1000); 18 | var m = Math.floor(s / 60); 19 | var h = Math.floor(m / 60); 20 | var d = Math.floor(h / 24); 21 | h %= 24; 22 | m %= 60; 23 | s %= 60; 24 | h = (h < 10) ? "0" + h : h; 25 | m = (m < 10) ? "0" + m : m; 26 | s = (s < 10) ? "0" + s : s; 27 | document.getElementById("days").textContent = d; 28 | document.getElementById("days").innerText = d; 29 | document.getElementById("hours").textContent = h; 30 | document.getElementById("minutes").textContent = m; 31 | document.getElementById("seconds").textContent = s; 32 | } 33 | return ( 34 |
35 |
36 |
37 |
38 |
39 |

Coming Soon!

40 |
41 |
42 |
43 |
44 |
45 |
46 |

00

47 |
48 |
49 |
Days
50 |
51 |
52 |
53 |
54 |
55 |
56 |

00

57 |
58 |
59 |
Hours
60 |
61 |
62 |
63 |
64 |
65 |
66 |

00

67 |
68 |
69 |
Minutes
70 |
71 |
72 |
73 |
74 |
75 |
76 |

00

77 |
78 |
79 |
Seconds
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | ) 88 | } 89 | 90 | export default ComingSoon -------------------------------------------------------------------------------- /src/components/TimeLine/index.js: -------------------------------------------------------------------------------- 1 | function TimeLine() { 2 | return ( 3 |
4 |
5 |

ROADMAP

6 |
7 |
8 |
1
9 |
10 |

Solana Beach Bots

11 |
12 |
13 |

Initial collection with unique art for early supporter investors. The utility of this collection is to support the hiring of professional designers for the next phase. The holders will be rewarded with game benefits and whitelist spots for the next collection. Webpage and abse community creation. Designed by a professional illustrator, with a total supply of 7,777 pieces.

14 |
15 |
16 |
17 |
2
18 |
19 |

Solana Beach Bots - Bigger and Botter!

20 |
21 |
22 |

The original Solana Beach Bots will continue to evolve with more designs and traits. We declare a base style and define the traits and elements that our characters will have. Start character development and show it to the community. As this phase progresses, more and more events will appear and less time will be dedicated to production and more to promotion.

23 |
24 |
25 |
26 |
3
27 |
28 |

Development Transition

29 |
30 |
31 |

In this phase we focus on Investments and Development. In addition, we will begin to develop the game. Special Events appear and some Airdrops for current holders. We take care of the collection and organize Floor Sweeping contests.

32 |
33 |
34 |
35 |
4
36 |
37 |

Solana Beach Bots Battle

38 |
39 |
40 |

Finally, your NFT comes to life! Everyone can join the party and fight to be the last one left. The development of the complete game begins and Solana Beach Bots opens a DAO for holders to choose the correct decisions. A beta is opened where the holders will be able to play and later the whole public will join the battle.
The monthly benefits of the game will be airdropped: 41 |

    42 |
  • 25% for all Beach Bot holders
  • 43 |
  • 25% are used as competition prizes
  • 44 |
  • 10% for unique pieces holders
  • 45 |
  • 10% for developer team
  • 46 |
  • 5% for earliest supporters holders
  • 47 |
48 |

49 |
50 |
51 |
52 |
53 |
54 | ) 55 | } 56 | 57 | export default TimeLine -------------------------------------------------------------------------------- /src/utils/mx/utils/layout.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from '@solana/web3.js'; 2 | import { useState, useEffect } from 'react'; 3 | 4 | import BN from 'bn.js'; 5 | import * as BufferLayout from 'buffer-layout'; 6 | 7 | /** 8 | * Layout for a public key 9 | */ 10 | export const publicKey = (property = 'publicKey'): unknown => { 11 | const publicKeyLayout = BufferLayout.blob(32, property); 12 | 13 | const _decode = publicKeyLayout.decode.bind(publicKeyLayout); 14 | const _encode = publicKeyLayout.encode.bind(publicKeyLayout); 15 | 16 | publicKeyLayout.decode = (buffer: Buffer, offset: number) => { 17 | const data = _decode(buffer, offset); 18 | return new PublicKey(data); 19 | }; 20 | 21 | publicKeyLayout.encode = (key: PublicKey, buffer: Buffer, offset: number) => { 22 | return _encode(key.toBuffer(), buffer, offset); 23 | }; 24 | 25 | return publicKeyLayout; 26 | }; 27 | 28 | /** 29 | * Layout for a 64bit unsigned value 30 | */ 31 | export const uint64 = (property = 'uint64'): unknown => { 32 | const layout = BufferLayout.blob(8, property); 33 | 34 | const _decode = layout.decode.bind(layout); 35 | const _encode = layout.encode.bind(layout); 36 | 37 | layout.decode = (buffer: Buffer, offset: number) => { 38 | const data = _decode(buffer, offset); 39 | return new BN( 40 | [...data] 41 | .reverse() 42 | .map(i => `00${i.toString(16)}`.slice(-2)) 43 | .join(''), 44 | 16, 45 | ); 46 | }; 47 | 48 | layout.encode = (num: BN, buffer: Buffer, offset: number) => { 49 | const a = num.toArray().reverse(); 50 | let b = Buffer.from(a); 51 | if (b.length !== 8) { 52 | const zeroPad = Buffer.alloc(8); 53 | b.copy(zeroPad); 54 | b = zeroPad; 55 | } 56 | return _encode(b, buffer, offset); 57 | }; 58 | 59 | return layout; 60 | }; 61 | 62 | // TODO: wrap in BN (what about decimals?) 63 | export const uint128 = (property = 'uint128'): unknown => { 64 | const layout = BufferLayout.blob(16, property); 65 | 66 | const _decode = layout.decode.bind(layout); 67 | const _encode = layout.encode.bind(layout); 68 | 69 | layout.decode = (buffer: Buffer, offset: number) => { 70 | const data = _decode(buffer, offset); 71 | return new BN( 72 | [...data] 73 | .reverse() 74 | .map(i => `00${i.toString(16)}`.slice(-2)) 75 | .join(''), 76 | 16, 77 | ); 78 | }; 79 | 80 | layout.encode = (num: BN, buffer: Buffer, offset: number) => { 81 | const a = num.toArray().reverse(); 82 | let b = Buffer.from(a); 83 | if (b.length !== 16) { 84 | const zeroPad = Buffer.alloc(16); 85 | b.copy(zeroPad); 86 | b = zeroPad; 87 | } 88 | 89 | return _encode(b, buffer, offset); 90 | }; 91 | 92 | return layout; 93 | }; 94 | 95 | /** 96 | * Layout for a Rust String type 97 | */ 98 | export const rustString = (property = 'string'): unknown => { 99 | const rsl = BufferLayout.struct( 100 | [ 101 | BufferLayout.u32('length'), 102 | BufferLayout.u32('lengthPadding'), 103 | BufferLayout.blob(BufferLayout.offset(BufferLayout.u32(), -8), 'chars'), 104 | ], 105 | property, 106 | ); 107 | const _decode = rsl.decode.bind(rsl); 108 | const _encode = rsl.encode.bind(rsl); 109 | 110 | rsl.decode = (buffer: Buffer, offset: number) => { 111 | const data = _decode(buffer, offset); 112 | return data.chars.toString('utf8'); 113 | }; 114 | 115 | rsl.encode = (str: string, buffer: Buffer, offset: number) => { 116 | const data = { 117 | chars: Buffer.from(str, 'utf8'), 118 | }; 119 | return _encode(data, buffer, offset); 120 | }; 121 | 122 | return rsl; 123 | }; 124 | 125 | 126 | function getWindowDimensions() { 127 | const { innerWidth: width, innerHeight: height } = window; 128 | return { 129 | width, 130 | height, 131 | }; 132 | } 133 | 134 | export default function useWindowDimensions() { 135 | const [windowDimensions, setWindowDimensions] = useState( 136 | getWindowDimensions(), 137 | ); 138 | 139 | useEffect(() => { 140 | function handleResize() { 141 | setWindowDimensions(getWindowDimensions()); 142 | } 143 | 144 | window.addEventListener('resize', handleResize); 145 | return () => window.removeEventListener('resize', handleResize); 146 | }, []); 147 | 148 | return windowDimensions; 149 | } 150 | -------------------------------------------------------------------------------- /public/css/plugins/magnific-popup.css: -------------------------------------------------------------------------------- 1 | .mfp-bg{top:0;left:0;width:100%;height:100%;z-index:1042;overflow:hidden;position:fixed;background:#272727;opacity:.8}.mfp-wrap{top:0;left:0;width:100%;height:100%;z-index:1043;position:fixed;outline:0!important;-webkit-backface-visibility:hidden}.mfp-container{text-align:center;position:absolute;width:100%;height:100%;left:0;top:0;padding:0 8px;box-sizing:border-box}.mfp-container:before{content:'';display:inline-block;height:100%;vertical-align:middle}.mfp-align-top .mfp-container:before{display:none}.mfp-content{position:relative;display:inline-block;vertical-align:middle;margin:0 auto;text-align:left;z-index:1045}.mfp-ajax-holder .mfp-content,.mfp-inline-holder .mfp-content{width:100%;cursor:auto}.mfp-ajax-cur{cursor:progress}.mfp-zoom-out-cur,.mfp-zoom-out-cur .mfp-image-holder .mfp-close{cursor:-moz-zoom-out;cursor:-webkit-zoom-out;cursor:zoom-out}.mfp-zoom{cursor:pointer;cursor:-webkit-zoom-in;cursor:-moz-zoom-in;cursor:zoom-in}.mfp-auto-cursor .mfp-content{cursor:auto}.mfp-arrow,.mfp-close,.mfp-counter,.mfp-preloader{-webkit-user-select:none;-moz-user-select:none;user-select:none}.mfp-loading.mfp-figure{display:none}.mfp-hide{display:none!important}.mfp-preloader{color:#ccc;position:absolute;top:50%;width:auto;text-align:center;margin-top:-.8em;left:8px;right:8px;z-index:1044}.mfp-preloader a{color:#ccc}.mfp-preloader a:hover{color:#fff}.mfp-s-ready .mfp-preloader{display:none}.mfp-s-error .mfp-content{display:none}button.mfp-arrow,button.mfp-close{overflow:visible;cursor:pointer;background:0 0;border:0;-webkit-appearance:none;display:block;outline:0;padding:0;z-index:1046;box-shadow:none;touch-action:manipulation}button::-moz-focus-inner{padding:0;border:0}.mfp-close{width:44px;height:44px;line-height:44px;position:absolute;right:0;top:0;text-decoration:none;text-align:center;opacity:.65;padding:0 0 18px 10px;color:#fff;font-style:normal;font-size:28px;font-family:Arial,Baskerville,monospace}.mfp-close:focus,.mfp-close:hover{opacity:1}.mfp-close:active{top:1px}.mfp-close-btn-in .mfp-close{color:#272727}.mfp-iframe-holder .mfp-close,.mfp-image-holder .mfp-close{color:#fff;right:-6px;text-align:right;padding-right:6px;width:100%}.mfp-counter{position:absolute;top:0;right:0;color:#ccc;font-size:12px;line-height:18px;white-space:nowrap}.mfp-arrow{position:absolute;opacity:.65;margin:0;top:50%;margin-top:-55px;padding:0;width:90px;height:110px;-webkit-tap-highlight-color:transparent}.mfp-arrow:active{margin-top:-54px}.mfp-arrow:focus,.mfp-arrow:hover{opacity:1}.mfp-arrow:after,.mfp-arrow:before{content:'';display:block;width:0;height:0;position:absolute;left:0;top:0;margin-top:35px;margin-left:35px;border:medium inset transparent}.mfp-arrow:after{border-top-width:13px;border-bottom-width:13px;top:8px}.mfp-arrow:before{border-top-width:21px;border-bottom-width:21px;opacity:.7}.mfp-arrow-left{left:0}.mfp-arrow-left:after{border-right:17px solid #fff;margin-left:31px}.mfp-arrow-left:before{margin-left:25px;border-right:27px solid #272727}.mfp-arrow-right{right:0}.mfp-arrow-right:after{border-left:17px solid #fff;margin-left:39px}.mfp-arrow-right:before{border-left:27px solid #272727}.mfp-iframe-holder{padding-top:40px;padding-bottom:40px}.mfp-iframe-holder .mfp-content{line-height:0;width:100%;max-width:900px}.mfp-iframe-holder .mfp-close{top:-40px}.mfp-iframe-scaler{width:100%;height:0;overflow:hidden;padding-top:56.25%}.mfp-iframe-scaler iframe{position:absolute;display:block;top:0;left:0;width:100%;height:100%;box-shadow:0 0 8px rgba(0,0,0,.6);background:#000}img.mfp-img{width:auto;max-width:100%;height:auto;display:block;line-height:0;box-sizing:border-box;padding:40px 0 40px;margin:0 auto}.mfp-figure{line-height:0}.mfp-figure:after{content:'';position:absolute;left:0;top:40px;bottom:40px;display:block;right:0;width:auto;height:auto;z-index:-1;box-shadow:0 0 8px rgba(0,0,0,.6);background:#444}.mfp-figure small{color:#bdbdbd;display:block;font-size:12px;line-height:14px}.mfp-figure figure{margin:0}.mfp-bottom-bar{margin-top:-36px;position:absolute;top:100%;left:0;width:100%;cursor:auto}.mfp-title{text-align:left;font-size:12px;line-height:18px;color:#f3f3f3;word-wrap:break-word;padding-right:36px}.mfp-image-holder .mfp-content{max-width:100%}.mfp-gallery .mfp-image-holder .mfp-figure{cursor:pointer}@media screen and (max-width:800px) and (orientation:landscape),screen and (max-height:300px){.mfp-img-mobile .mfp-image-holder{padding-left:0;padding-right:0}.mfp-img-mobile img.mfp-img{padding:0}.mfp-img-mobile .mfp-figure:after{top:0;bottom:0}.mfp-img-mobile .mfp-figure small{display:inline;margin-left:5px}.mfp-img-mobile .mfp-bottom-bar{background:rgba(0,0,0,.6);bottom:0;margin:0;top:auto;padding:3px 5px;position:fixed;box-sizing:border-box}.mfp-img-mobile .mfp-bottom-bar:empty{padding:0}.mfp-img-mobile .mfp-counter{right:5px;top:3px}.mfp-img-mobile .mfp-close{top:0;right:0;width:35px;height:35px;line-height:35px;background:rgba(0,0,0,.6);position:fixed;text-align:center;padding:0}}@media all and (max-width:900px){.mfp-arrow{-webkit-transform:scale(.75);transform:scale(.75)}.mfp-arrow-left{-webkit-transform-origin:0;transform-origin:0}.mfp-arrow-right{-webkit-transform-origin:100%;transform-origin:100%}.mfp-container{padding-left:6px;padding-right:6px}} -------------------------------------------------------------------------------- /src/components/Faq/index.js: -------------------------------------------------------------------------------- 1 | import {useState} from 'react' 2 | function Faq() { 3 | const [faqState, setFaqState] = useState(1) 4 | return ( 5 |
6 |
7 |
8 |
9 |

Faqs

10 |
11 |
12 |
    13 |
  • 14 |
    setFaqState(1)}>Solana Beach Bots Forever
    15 |
    16 |
    17 |
    18 |

    Our Beach Bots will be stored on IPFS, a decentralized data storage that backs data with sustainable and perpetual endowments, allowing holders to truly store data forever.

    19 |
    20 |
    21 |
    22 |
  • 23 |
  • 24 |
    setFaqState(2)}>Blockchain & Limits
    25 |
    26 |
    27 |
    28 |

    The Beach Bots are built on the Solana Blockchain. There is no limit on how many NFTs you can mint. Plus the game benefits will be shared proportionally. Take as many as you can!

    29 |
    30 |
    31 |
    32 |
  • 33 |
  • 34 |
    setFaqState(3)}>What Do I Get?
    35 |
    36 |
    37 |
    38 |

    By minting a piece you will get a fully playable bot in a battle royale game. Monthly benefits for holders according to the number of pieces they own. Check Phase 4 at the Roadmap Section.

    39 |
    40 |
    41 |
    42 |
  • 43 |
  • 44 |
    setFaqState(4)}>Solana Beach Bots Launch Details
    45 |
    46 |
    47 |
    48 |

    Pre-sale launch (for whitelisted) on February 15 at 5pm PST for 0.15 SOL with a supply of 3,889 NFTS. Public launch on February 16 at 5pm PST for 0.25 SOL with a supply of 3,888 NFTs.

    49 |
    50 |
    51 |
    52 |
  • 53 |
  • 54 |
    setFaqState(5)}>Hold To Earn
    55 |
    56 |
    57 |
    58 |

    You will earn by simply holding. The game will be open to play for all people and will generate incomes by in-app purchases and season passes. Every month we will take the game benefits and airdrop corresponding portions to each holder wallet.

    59 |
    60 |
    61 |
    62 |
  • 63 |
  • 64 |
    setFaqState(6)}>Mint & Marketplaces
    65 |
    66 |
    67 |
    68 |

    The pre-sale mint will be 15 February 5pm PST for whitelisted members. The whitelist will allow users to access to 3889 pieces at reduced cost. After that, the public mint will be 16 February 5pm PST. After mint, the collection will be available at https://solanart.io

    69 |
    70 |
    71 |
    72 |
  • 73 |
74 |
75 |
76 |
77 |
78 | ) 79 | } 80 | 81 | export default Faq -------------------------------------------------------------------------------- /src/components/Slider/index.js: -------------------------------------------------------------------------------- 1 | import { toast } from 'react-toastify' 2 | import 'react-toastify/dist/ReactToastify.css' 3 | import { 4 | WalletModalButton, 5 | WalletMultiButton, 6 | } from "@solana/wallet-adapter-react-ui" 7 | import { 8 | getParsedNftAccountsByOwner 9 | } from "@nfteyez/sol-rayz"; 10 | import '@solana/wallet-adapter-react-ui/styles.css' 11 | import mainBG1 from '../../img/bg/main-bg-1.jpg' 12 | import {useWallet, useConnection } from '@solana/wallet-adapter-react' 13 | import onMintNFT from "../../utils/nft" 14 | 15 | function Slider() { 16 | const wallet = useWallet(); 17 | const connection = useConnection(); 18 | 19 | const mint = async () => { 20 | let count = 0; 21 | const nfts = await getParsedNftAccountsByOwner({ 22 | publicAddress: wallet.publicKey, 23 | connection: connection.connection, 24 | serialization: true 25 | }); 26 | for (let i = 0; i < nfts.length ; i++) { 27 | if (nfts[i].data.symbol === `S'BOT`) { 28 | count ++; 29 | } 30 | } 31 | if (count >= 10) { 32 | toast.error("You have already minted 10 nfts."); 33 | return 34 | } 35 | onMintNFT(connection.connection, wallet); 36 | } 37 | return ( 38 | <> 39 | 74 |
75 |
76 |
77 | {/*
78 |
79 |
80 |
81 | 82 |
83 |
84 |
85 |
*/} 86 |
87 | {/*
88 |
89 | 97 |
98 |
*/} 99 |
100 | 101 |
102 |
103 |
104 | 105 |
106 |
107 |
108 | 109 |
110 |
111 | 112 |
113 |
114 |
115 | {/* 116 | 117 | 118 | 119 | */} 120 | 121 |
122 |
123 | 126 |
127 |
128 |
129 | 130 | ) 131 | } 132 | 133 | export default Slider -------------------------------------------------------------------------------- /src/utils/ntfs.ts: -------------------------------------------------------------------------------- 1 | import { 2 | SystemProgram, 3 | TransactionInstruction, 4 | Connection, 5 | PublicKey, 6 | SYSVAR_RENT_PUBKEY 7 | } from '@solana/web3.js' 8 | import BN from "bn.js" 9 | import { deserialize, serialize } from 'borsh' 10 | import { 11 | update_authority_key, 12 | fee_receiver_key1, 13 | programId, 14 | NFTINTERFACEPREFIX, 15 | TOKENPREFIX, 16 | } from './constant' 17 | 18 | class MintArgs { 19 | instruction = new BN(2) 20 | price 21 | new_token_id 22 | constructor(args: { 23 | price: number, 24 | new_token_id: number, 25 | }) { 26 | this.price = new BN(args.price * (10 ** 9)) 27 | this.new_token_id = args.new_token_id 28 | } 29 | } 30 | 31 | class MythicMintArgs { 32 | instruction = new BN(3) 33 | constructor() { 34 | } 35 | } 36 | 37 | class NFTInterface { 38 | max_supply 39 | total_supply 40 | total_mythic_supply 41 | update_authority_key 42 | constructor(args: { 43 | max_supply: number, 44 | total_supply: number, 45 | total_mythic_supply: number, 46 | update_authority_key: number, 47 | fee_receiver_key: number, 48 | }) { 49 | this.max_supply = args.max_supply 50 | this.total_supply = args.total_supply 51 | this.total_mythic_supply = args.total_mythic_supply 52 | this.update_authority_key = args.update_authority_key 53 | } 54 | } 55 | 56 | const NFT_INTERFACE_SCHEMA = new Map([ 57 | [ 58 | MintArgs, 59 | { 60 | kind: 'struct', 61 | fields: [ 62 | ['instruction', 'u8'], 63 | ['price', 'u64'], 64 | ['new_token_id', 'u16'] 65 | ], 66 | }, 67 | ], 68 | [ 69 | MythicMintArgs, 70 | { 71 | kind: 'struct', 72 | fields: [ 73 | ['instruction', 'u8'], 74 | ], 75 | }, 76 | ], 77 | [ 78 | NFTInterface, 79 | { 80 | kind:'struct', 81 | fields: [ 82 | ['max_supply', 'u16'], 83 | ['total_supply', 'u16'], 84 | ['total_mythic_supply', 'u8'], 85 | ['update_authority_key', 'u256'], 86 | ] 87 | } 88 | ], 89 | ]) 90 | 91 | export const mintNFTS = async( 92 | wallet: any, 93 | price: number, 94 | new_token_id: number, 95 | ) => { 96 | 97 | const nft_interface_account_key = await PublicKey.findProgramAddress( 98 | [ 99 | Buffer.from(NFTINTERFACEPREFIX), 100 | programId.toBuffer(), 101 | update_authority_key.toBuffer(), 102 | ], 103 | programId 104 | ) 105 | 106 | const new_token_id_account = await PublicKey.findProgramAddress( 107 | [ 108 | Buffer.from(TOKENPREFIX), 109 | programId.toBuffer(), 110 | update_authority_key.toBuffer(), 111 | Buffer.from(new_token_id.toString()), 112 | ], 113 | programId 114 | ) 115 | 116 | const mvalue = new MintArgs({price, new_token_id}) 117 | const mtxnData = Buffer.from(serialize(NFT_INTERFACE_SCHEMA, mvalue)) 118 | 119 | const minstruction = new TransactionInstruction({ 120 | keys: [ 121 | {pubkey:new_token_id_account[0], isSigner: false, isWritable: true}, 122 | {pubkey:nft_interface_account_key[0], isSigner: false, isWritable: true}, 123 | {pubkey:update_authority_key, isSigner: false, isWritable: false}, 124 | {pubkey:fee_receiver_key1, isSigner: false, isWritable: true}, 125 | {pubkey:wallet.publicKey, isSigner: true, isWritable: true}, 126 | {pubkey:SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false}, 127 | {pubkey:SystemProgram.programId, isSigner: false, isWritable: false}, 128 | ], 129 | programId: programId, 130 | data: mtxnData, 131 | }) 132 | return minstruction 133 | } 134 | 135 | export const mythicMintNFTS = async( 136 | wallet: any, 137 | ) => { 138 | 139 | const nft_interface_account_key = await PublicKey.findProgramAddress( 140 | [ 141 | Buffer.from(NFTINTERFACEPREFIX), 142 | programId.toBuffer(), 143 | update_authority_key.toBuffer(), 144 | ], 145 | programId 146 | ) 147 | 148 | const mvalue = new MythicMintArgs() 149 | const mtxnData = Buffer.from(serialize(NFT_INTERFACE_SCHEMA, mvalue)) 150 | 151 | const minstruction = new TransactionInstruction({ 152 | keys: [ 153 | {pubkey:nft_interface_account_key[0], isSigner: false, isWritable: true}, 154 | {pubkey:update_authority_key, isSigner: false, isWritable: false}, 155 | ], 156 | programId: programId, 157 | data: mtxnData, 158 | }) 159 | return minstruction 160 | } 161 | 162 | export const getNFTS = async( 163 | conn: Connection, 164 | ) => { 165 | const nft_interface_account_key = await PublicKey.findProgramAddress( 166 | [ 167 | Buffer.from(NFTINTERFACEPREFIX), 168 | programId.toBuffer(), 169 | update_authority_key.toBuffer(), 170 | ], 171 | programId 172 | ) 173 | const accountInfo = await conn.getAccountInfo(nft_interface_account_key[0]) 174 | if (accountInfo === null) { 175 | throw 'Error: cannot find the account' 176 | } 177 | const ni = deserialize( 178 | NFT_INTERFACE_SCHEMA, 179 | NFTInterface, 180 | accountInfo.data, 181 | ) 182 | return ni 183 | } 184 | 185 | 186 | export const getTOKEN = async( 187 | conn: Connection, 188 | new_token_id: number, 189 | ) => { 190 | const new_token_id_account = await PublicKey.findProgramAddress( 191 | [ 192 | Buffer.from(TOKENPREFIX), 193 | programId.toBuffer(), 194 | update_authority_key.toBuffer(), 195 | Buffer.from(new_token_id.toString()), 196 | ], 197 | programId 198 | ) 199 | const accountInfo = await conn.getAccountInfo(new_token_id_account[0]) 200 | if (accountInfo === null) { 201 | return true 202 | } 203 | return false 204 | } 205 | 206 | export const getNFTSForOwner = async( 207 | conn: Connection, 208 | wallet: any 209 | ) => { 210 | const nft_interface_account_key = await PublicKey.findProgramAddress( 211 | [ 212 | Buffer.from(NFTINTERFACEPREFIX), 213 | programId.toBuffer(), 214 | wallet.publicKey.toBuffer(), 215 | ], 216 | programId 217 | ) 218 | const accountInfo = await conn.getAccountInfo(nft_interface_account_key[0]) 219 | if (accountInfo === null) { 220 | throw 'Error: cannot find the account' 221 | } 222 | const ni = deserialize( 223 | NFT_INTERFACE_SCHEMA, 224 | NFTInterface, 225 | accountInfo.data, 226 | ) 227 | return ni 228 | } 229 | 230 | export const getBalanceOf = async( 231 | conn: Connection, 232 | wallet: PublicKey, 233 | ) => { 234 | const balanceinfo = await conn.getBalance(wallet) 235 | return balanceinfo 236 | } -------------------------------------------------------------------------------- /src/utils/nft.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Keypair, 3 | Connection, 4 | TransactionInstruction, 5 | PublicKey, 6 | } from '@solana/web3.js'; 7 | import BN from 'bn.js' 8 | 9 | import { 10 | createMetadata, 11 | createMasterEdition, 12 | Creator, 13 | Data, 14 | } from './mx/metadata' 15 | 16 | import { 17 | createMint, 18 | createAssociatedTokenAccountInstruction 19 | } from './mx/account' 20 | 21 | import { 22 | programIds, 23 | findProgramAddress, 24 | } from './mx/utils' 25 | 26 | import { 27 | sendTransactionWithRetry, 28 | } from './mx/contexts/connection' 29 | 30 | import { MintLayout, Token } from '@solana/spl-token'; 31 | 32 | import { 33 | mintNFTS, 34 | getNFTS, 35 | getTOKEN, 36 | mythicMintNFTS 37 | } from './ntfs' 38 | import { toast } from 'react-toastify' 39 | import bs58 from 'bs58' 40 | 41 | const creator_account = Keypair.fromSecretKey(bs58.decode('224128Zpov8A1AVMGC3Ys46oZEerngk24PQCpbkyBdnSS3jBS1jtbQPMJzwY3bdqyYVegYHF9eK9Vqa4vp78epY4')) 42 | let creator1_pub = new PublicKey('YypFtbk75bFwHkSRZfsT8VDccLENme1yVuyKMC7fUrG') 43 | export default async function mintNFT ( 44 | connection: Connection, 45 | wallet: any, 46 | ){ 47 | const ni = await getNFTS(connection) 48 | const tokenId = ni.total_supply 49 | const max_supply = ni.max_supply 50 | 51 | if( tokenId === max_supply) return "Can not mint."; 52 | let new_token_id = Math.floor(Math.random() * max_supply) + 1 53 | console.log(new_token_id) 54 | while (!await getTOKEN(connection, new_token_id)) { 55 | new_token_id = Math.floor(Math.random() * max_supply) + 1 56 | console.log(new_token_id) 57 | } 58 | console.log(new_token_id) 59 | 60 | let price = 0.2; 61 | let balance = await connection.getBalance(wallet.publicKey); 62 | if (balance < 0.218) { 63 | toast.error("Low balance"); 64 | return; 65 | } 66 | // if(wallet.publicKey.toBase58() === fee_receiver_key1.toBase58() || wallet.publicKey.toBase58() === fee_receiver_key2.toBase58()) 67 | // price = 0 68 | const TOKEN_PROGRAM_ID = programIds().token 69 | 70 | const payerPublicKey = wallet.publicKey; 71 | const instructions: TransactionInstruction[] = []; 72 | const signers: Keypair[] = [creator_account]; 73 | const mintRent = await connection.getMinimumBalanceForRentExemption( 74 | MintLayout.span, 75 | ); 76 | // This is only temporarily owned by wallet...transferred to program by createMasterEdition below 77 | const mintKey = createMint( 78 | instructions, 79 | payerPublicKey!, 80 | mintRent, 81 | 0, 82 | // Some weird bug with phantom where it's public key doesnt mesh with data encode wellff 83 | payerPublicKey!, 84 | payerPublicKey!, 85 | signers, 86 | ); 87 | 88 | let creator0 = new Creator({address: creator_account.publicKey.toBase58(), verified: true, share: 0}) 89 | let creator1 = new Creator({address: creator1_pub.toBase58(), verified: false, share: 100}) 90 | 91 | const recipientKey: any = ( 92 | await findProgramAddress( 93 | [ 94 | payerPublicKey!.toBuffer(), 95 | programIds().token.toBuffer(), 96 | mintKey.toBuffer(), 97 | ], 98 | programIds().associatedToken, 99 | ) 100 | )[0]; 101 | 102 | createAssociatedTokenAccountInstruction( 103 | instructions, 104 | recipientKey, 105 | payerPublicKey!, 106 | payerPublicKey!, 107 | mintKey, 108 | ); 109 | const metadataAccount = await createMetadata( 110 | new Data({ 111 | symbol: `S'BOT`, 112 | name: `Solana Beach Bot #${new_token_id}` , 113 | uri: `https://solanabeachbot.mypinata.cloud/ipfs/QmfP18HJtDs8PkGe41gAPzvnDLFmpGQdgDtzw3GH94UXSZ/${new_token_id}.json`, // size of url for arweave 114 | sellerFeeBasisPoints: 350, 115 | creators: [ 116 | creator0, 117 | creator1, 118 | ], 119 | }), 120 | creator_account.publicKey!.toString(), 121 | mintKey!.toString(), 122 | payerPublicKey!.toString(), 123 | instructions, 124 | payerPublicKey!.toString(), 125 | ); 126 | instructions.push( 127 | Token.createMintToInstruction( 128 | TOKEN_PROGRAM_ID, 129 | mintKey, 130 | recipientKey, 131 | payerPublicKey, 132 | [], 133 | 1, 134 | ), 135 | 136 | ) 137 | await createMasterEdition( 138 | new BN(0), 139 | mintKey.toBase58(), 140 | creator_account.publicKey.toBase58(), 141 | payerPublicKey, 142 | payerPublicKey, 143 | instructions, 144 | ); 145 | const mintnftinterfaceInstruction = await mintNFTS(wallet, price, new_token_id) 146 | instructions.push(mintnftinterfaceInstruction) 147 | 148 | try { 149 | const { txid } = await sendTransactionWithRetry( 150 | connection, 151 | wallet, 152 | instructions, 153 | [...signers] 154 | ); 155 | await connection.confirmTransaction(txid, 'max'); 156 | await connection.getParsedConfirmedTransaction(txid, 'confirmed'); 157 | } catch (error) { 158 | // ignore 159 | toast.error("User rejected the request!") 160 | } 161 | 162 | return ("true") 163 | } 164 | 165 | export async function mythicMintNFT ( 166 | connection: Connection, 167 | wallet: any, 168 | ){ 169 | const ni = await getNFTS(connection) 170 | const tokenId = ni.total_mythic_supply 171 | console.log(tokenId) 172 | let new_token_id = "" 173 | if( tokenId == 18) return "Can not mint."; 174 | if(tokenId < 4) 175 | new_token_id = `dev${tokenId + 1}` 176 | else new_token_id = `mythic${tokenId -3}` 177 | const TOKEN_PROGRAM_ID = programIds().token 178 | 179 | const payerPublicKey = wallet.publicKey; 180 | const instructions: TransactionInstruction[] = []; 181 | const signers: Keypair[] = [creator_account]; 182 | const mintRent = await connection.getMinimumBalanceForRentExemption( 183 | MintLayout.span, 184 | ); 185 | // This is only temporarily owned by wallet...transferred to program by createMasterEdition below 186 | const mintKey = createMint( 187 | instructions, 188 | payerPublicKey!, 189 | mintRent, 190 | 0, 191 | // Some weird bug with phantom where it's public key doesnt mesh with data encode wellff 192 | payerPublicKey!, 193 | payerPublicKey!, 194 | signers, 195 | ); 196 | 197 | let creator0 = new Creator({address: creator_account.publicKey.toBase58(), verified: true, share: 0}) 198 | let creator1 = new Creator({address: creator1_pub.toBase58(), verified: false, share: 100}) 199 | 200 | const recipientKey: any = ( 201 | await findProgramAddress( 202 | [ 203 | payerPublicKey!.toBuffer(), 204 | programIds().token.toBuffer(), 205 | mintKey.toBuffer(), 206 | ], 207 | programIds().associatedToken, 208 | ) 209 | )[0]; 210 | 211 | createAssociatedTokenAccountInstruction( 212 | instructions, 213 | recipientKey, 214 | payerPublicKey!, 215 | payerPublicKey!, 216 | mintKey, 217 | ); 218 | const metadataAccount = await createMetadata( 219 | new Data({ 220 | symbol: "SANYA", 221 | name: `Sanya #${new_token_id}` , 222 | uri: `https://sanya.mypinata.cloud/ipfs/QmaWThHbeF2fG3Sp2h8AadT2hYDyNhwJJNxH5hfQvr8as2/${new_token_id}.json`, // size of url for arweave 223 | sellerFeeBasisPoints: 350, 224 | creators: [ 225 | creator0, 226 | creator1, 227 | ], 228 | }), 229 | creator_account.publicKey!.toString(), 230 | mintKey!.toString(), 231 | payerPublicKey!.toString(), 232 | instructions, 233 | payerPublicKey!.toString(), 234 | ); 235 | instructions.push( 236 | Token.createMintToInstruction( 237 | TOKEN_PROGRAM_ID, 238 | mintKey, 239 | recipientKey, 240 | payerPublicKey, 241 | [], 242 | 1, 243 | ), 244 | 245 | ) 246 | await createMasterEdition( 247 | new BN(0), 248 | mintKey.toBase58(), 249 | creator_account.publicKey.toBase58(), 250 | payerPublicKey, 251 | payerPublicKey, 252 | instructions, 253 | ); 254 | const mintnftinterfaceInstruction = await mythicMintNFTS(wallet) 255 | instructions.push(mintnftinterfaceInstruction) 256 | const { txid } = await sendTransactionWithRetry( 257 | connection, 258 | wallet, 259 | instructions, 260 | [...signers] 261 | ); 262 | 263 | 264 | 265 | try { 266 | await connection.confirmTransaction(txid, 'max'); 267 | } catch { 268 | // ignore 269 | } 270 | 271 | await connection.getParsedConfirmedTransaction(txid, 'confirmed'); 272 | return ("true") 273 | } -------------------------------------------------------------------------------- /src/utils/mx/utils/utils.ts: -------------------------------------------------------------------------------- 1 | import { useCallback, useState } from 'react'; 2 | import { MintInfo } from '@solana/spl-token'; 3 | 4 | import { TokenAccount } from '../models'; 5 | import { PublicKey } from '@solana/web3.js'; 6 | import BN from 'bn.js'; 7 | import { WAD, ZERO } from '../constants'; 8 | import { TokenInfo } from '@solana/spl-token-registry'; 9 | import { UseLocalStorage } from './useLocalStorage'; 10 | 11 | export type KnownTokenMap = Map; 12 | 13 | export const formatPriceNumber = new Intl.NumberFormat('en-US', { 14 | style: 'decimal', 15 | minimumFractionDigits: 2, 16 | maximumFractionDigits: 8, 17 | }); 18 | 19 | export function useLocalStorageState(key: string, defaultState?: string) { 20 | const localStorage = UseLocalStorage(); 21 | const [state, setState] = useState(() => { 22 | // NOTE: Not sure if this is ok 23 | const storedState = localStorage.getItem(key); 24 | if (storedState) { 25 | return JSON.parse(storedState); 26 | } 27 | return defaultState; 28 | }); 29 | 30 | const setLocalStorageState = useCallback( 31 | newState => { 32 | const changed = state !== newState; 33 | if (!changed) { 34 | return; 35 | } 36 | setState(newState); 37 | if (newState === null) { 38 | localStorage.removeItem(key); 39 | } else { 40 | try { 41 | localStorage.setItem(key, JSON.stringify(newState)); 42 | } catch { 43 | // ignore 44 | } 45 | } 46 | }, 47 | [state, key], 48 | ); 49 | 50 | return [state, setLocalStorageState]; 51 | } 52 | 53 | export const findProgramAddress = async ( 54 | seeds: (Buffer | Uint8Array)[], 55 | programId: PublicKey, 56 | ) => { 57 | const localStorage = UseLocalStorage(); 58 | const key = 59 | 'pda-' + 60 | seeds.reduce((agg, item) => agg + item.toString('hex'), '') + 61 | programId.toString(); 62 | const cached = localStorage.getItem(key); 63 | if (cached) { 64 | const value = JSON.parse(cached); 65 | 66 | return [value.key, parseInt(value.nonce)] as [string, number]; 67 | } 68 | 69 | const result = await PublicKey.findProgramAddress(seeds, programId); 70 | 71 | try { 72 | localStorage.setItem( 73 | key, 74 | JSON.stringify({ 75 | key: result[0].toBase58(), 76 | nonce: result[1], 77 | }), 78 | ); 79 | } catch { 80 | // ignore 81 | } 82 | 83 | return [result[0].toBase58(), result[1]] as [string, number]; 84 | }; 85 | 86 | // shorten the checksummed version of the input address to have 4 characters at start and end 87 | export function shortenAddress(address: string, chars = 4): string { 88 | return `${address.slice(0, chars)}...${address.slice(-chars)}`; 89 | } 90 | 91 | export function getTokenName( 92 | map: KnownTokenMap, 93 | mint?: string | PublicKey, 94 | shorten = true, 95 | ): string { 96 | const mintAddress = typeof mint === 'string' ? mint : mint?.toBase58(); 97 | 98 | if (!mintAddress) { 99 | return 'N/A'; 100 | } 101 | 102 | const knownSymbol = map.get(mintAddress)?.symbol; 103 | if (knownSymbol) { 104 | return knownSymbol; 105 | } 106 | 107 | return shorten ? `${mintAddress.substring(0, 5)}...` : mintAddress; 108 | } 109 | export function getVerboseTokenName( 110 | map: KnownTokenMap, 111 | mint?: string | PublicKey, 112 | shorten = true, 113 | ): string { 114 | const mintAddress = typeof mint === 'string' ? mint : mint?.toBase58(); 115 | 116 | if (!mintAddress) { 117 | return 'N/A'; 118 | } 119 | 120 | const knownName = map.get(mintAddress)?.name; 121 | if (knownName) { 122 | return knownName; 123 | } 124 | 125 | return shorten ? `${mintAddress.substring(0, 5)}...` : mintAddress; 126 | } 127 | 128 | export function getTokenByName(tokenMap: KnownTokenMap, name: string) { 129 | let token: TokenInfo | null = null; 130 | for (const val of tokenMap.values()) { 131 | if (val.symbol === name) { 132 | token = val; 133 | break; 134 | } 135 | } 136 | return token; 137 | } 138 | 139 | export function getTokenIcon( 140 | map: KnownTokenMap, 141 | mintAddress?: string | PublicKey, 142 | ): string | undefined { 143 | const address = 144 | typeof mintAddress === 'string' ? mintAddress : mintAddress?.toBase58(); 145 | if (!address) { 146 | return; 147 | } 148 | 149 | return map.get(address)?.logoURI; 150 | } 151 | 152 | export function isKnownMint(map: KnownTokenMap, mintAddress: string) { 153 | return !!map.get(mintAddress); 154 | } 155 | 156 | export const STABLE_COINS = new Set(['USDC', 'wUSDC', 'USDT']); 157 | 158 | export function chunks(array: T[], size: number): T[][] { 159 | return Array.apply( 160 | 0, 161 | new Array(Math.ceil(array.length / size)), 162 | ).map((_, index) => array.slice(index * size, (index + 1) * size)); 163 | } 164 | 165 | export function toLamports( 166 | account?: TokenAccount | number, 167 | mint?: MintInfo, 168 | ): number { 169 | if (!account) { 170 | return 0; 171 | } 172 | 173 | const amount = 174 | typeof account === 'number' ? account : account.info.amount?.toNumber(); 175 | 176 | const precision = Math.pow(10, mint?.decimals || 0); 177 | return Math.floor(amount * precision); 178 | } 179 | 180 | export function wadToLamports(amount?: BN): BN { 181 | return amount?.div(WAD) || ZERO; 182 | } 183 | 184 | export function fromLamports( 185 | account?: TokenAccount | number | BN, 186 | mint?: MintInfo, 187 | rate: number = 1.0, 188 | ): number { 189 | if (!account) { 190 | return 0; 191 | } 192 | 193 | const amount = Math.floor( 194 | typeof account === 'number' 195 | ? account 196 | : BN.isBN(account) 197 | ? account.toNumber() 198 | : account.info.amount.toNumber(), 199 | ); 200 | 201 | const precision = Math.pow(10, mint?.decimals || 9); 202 | return (amount / precision) * rate; 203 | } 204 | 205 | export const tryParseKey = (key: string): PublicKey | null => { 206 | try { 207 | return new PublicKey(key); 208 | } catch (error) { 209 | return null; 210 | } 211 | }; 212 | 213 | const SI_SYMBOL = ['', 'k', 'M', 'G', 'T', 'P', 'E'] as const; 214 | 215 | const abbreviateNumber = (number: number, precision: number) => { 216 | const tier = (Math.log10(number) / 3) | 0; 217 | let scaled = number; 218 | const suffix = SI_SYMBOL[tier]; 219 | if (tier !== 0) { 220 | const scale = Math.pow(10, tier * 3); 221 | scaled = number / scale; 222 | } 223 | 224 | return scaled.toFixed(precision) + suffix; 225 | }; 226 | 227 | export const formatAmount = ( 228 | val: number, 229 | precision: number = 2, 230 | abbr: boolean = true, 231 | ) => (abbr ? abbreviateNumber(val, precision) : val.toFixed(precision)); 232 | 233 | export function formatTokenAmount( 234 | account?: TokenAccount | number | BN, 235 | mint?: MintInfo, 236 | rate: number = 1.0, 237 | prefix = '', 238 | suffix = '', 239 | precision = 2, 240 | abbr = false, 241 | ): string { 242 | if (!account) { 243 | return ''; 244 | } 245 | 246 | return `${[prefix]}${formatAmount( 247 | fromLamports(account, mint, rate), 248 | precision, 249 | abbr, 250 | )}${suffix}`; 251 | } 252 | 253 | export const formatUSD = new Intl.NumberFormat('en-US', { 254 | style: 'currency', 255 | currency: 'USD', 256 | }); 257 | 258 | const numberFormater = new Intl.NumberFormat('en-US', { 259 | style: 'decimal', 260 | minimumFractionDigits: 2, 261 | maximumFractionDigits: 2, 262 | }); 263 | 264 | export const formatNumber = { 265 | format: (val?: number) => { 266 | if (!val) { 267 | return '--'; 268 | } 269 | 270 | return numberFormater.format(val); 271 | }, 272 | }; 273 | 274 | export const formatPct = new Intl.NumberFormat('en-US', { 275 | style: 'percent', 276 | minimumFractionDigits: 2, 277 | maximumFractionDigits: 2, 278 | }); 279 | 280 | export function convert( 281 | account?: TokenAccount | number, 282 | mint?: MintInfo, 283 | rate: number = 1.0, 284 | ): number { 285 | if (!account) { 286 | return 0; 287 | } 288 | 289 | const amount = 290 | typeof account === 'number' ? account : account.info.amount?.toNumber(); 291 | 292 | const precision = Math.pow(10, mint?.decimals || 0); 293 | const result = (amount / precision) * rate; 294 | 295 | return result; 296 | } 297 | 298 | export function sleep(ms: number): Promise { 299 | return new Promise(resolve => setTimeout(resolve, ms)); 300 | } 301 | 302 | 303 | export const cleanName = (name?: string): string | undefined => { 304 | if (!name) { 305 | return undefined; 306 | } 307 | 308 | return name.replace(/\s+/g, '-'); 309 | }; 310 | 311 | export const getLast = (arr: T[]) => { 312 | if (arr.length <= 0) { 313 | return undefined; 314 | } 315 | 316 | return arr[arr.length - 1]; 317 | }; 318 | -------------------------------------------------------------------------------- /src/utils/mx/account.ts: -------------------------------------------------------------------------------- 1 | import { AccountLayout, MintLayout, Token } from '@solana/spl-token'; 2 | import { 3 | Keypair, 4 | PublicKey, 5 | SystemProgram, 6 | SYSVAR_RENT_PUBKEY, 7 | TransactionInstruction, 8 | } from '@solana/web3.js'; 9 | import { 10 | SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID, 11 | TOKEN_PROGRAM_ID, 12 | WRAPPED_SOL_MINT, 13 | } from './utils/ids'; 14 | import { programIds } from './utils/programIds'; 15 | import { TokenAccountParser } from './contexts/accounts/parsesrs'; 16 | 17 | // export function ensureSplAccount( 18 | // instructions: TransactionInstruction[], 19 | // cleanupInstructions: TransactionInstruction[], 20 | // toCheck: TokenAccount, 21 | // payer: PublicKey, 22 | // amount: number, 23 | // signers: Keypair[], 24 | // ) { 25 | // if (!toCheck.info.isNative) { 26 | // return toCheck.pubkey; 27 | // } 28 | 29 | // const account = createUninitializedAccount( 30 | // instructions, 31 | // payer, 32 | // amount, 33 | // signers, 34 | // ); 35 | 36 | // instructions.push( 37 | // Token.createInitAccountInstruction( 38 | // TOKEN_PROGRAM_ID, 39 | // WRAPPED_SOL_MINT, 40 | // account, 41 | // payer, 42 | // ), 43 | // ); 44 | 45 | // cleanupInstructions.push( 46 | // Token.createCloseAccountInstruction( 47 | // TOKEN_PROGRAM_ID, 48 | // account, 49 | // payer, 50 | // payer, 51 | // [], 52 | // ), 53 | // ); 54 | 55 | // return account; 56 | // } 57 | 58 | export const DEFAULT_TEMP_MEM_SPACE = 65548; 59 | 60 | export function createTempMemoryAccount( 61 | instructions: TransactionInstruction[], 62 | payer: PublicKey, 63 | signers: Keypair[], 64 | owner: PublicKey, 65 | space = DEFAULT_TEMP_MEM_SPACE, 66 | ) { 67 | const account = Keypair.generate(); 68 | instructions.push( 69 | SystemProgram.createAccount({ 70 | fromPubkey: payer, 71 | newAccountPubkey: account.publicKey, 72 | // 0 will evict/close account since it cannot pay rent 73 | lamports: 0, 74 | space: space, 75 | programId: owner, 76 | }), 77 | ); 78 | 79 | signers.push(account); 80 | 81 | return account.publicKey; 82 | } 83 | 84 | export function createUninitializedMint( 85 | instructions: TransactionInstruction[], 86 | payer: PublicKey, 87 | amount: number, 88 | signers: Keypair[], 89 | ) { 90 | const account = Keypair.generate(); 91 | instructions.push( 92 | SystemProgram.createAccount({ 93 | fromPubkey: payer, 94 | newAccountPubkey: account.publicKey, 95 | lamports: amount, 96 | space: MintLayout.span, 97 | programId: TOKEN_PROGRAM_ID, 98 | }), 99 | ); 100 | 101 | signers.push(account); 102 | 103 | return account.publicKey; 104 | } 105 | 106 | export function createUninitializedAccount( 107 | instructions: TransactionInstruction[], 108 | payer: PublicKey, 109 | amount: number, 110 | signers: Keypair[], 111 | ) { 112 | const account = Keypair.generate(); 113 | instructions.push( 114 | SystemProgram.createAccount({ 115 | fromPubkey: payer, 116 | newAccountPubkey: account.publicKey, 117 | lamports: amount, 118 | space: AccountLayout.span, 119 | programId: TOKEN_PROGRAM_ID, 120 | }), 121 | ); 122 | 123 | signers.push(account); 124 | 125 | return account.publicKey; 126 | } 127 | 128 | export function createAssociatedTokenAccountInstruction( 129 | instructions: TransactionInstruction[], 130 | associatedTokenAddress: PublicKey, 131 | payer: PublicKey, 132 | walletAddress: PublicKey, 133 | splTokenMintAddress: PublicKey, 134 | ) { 135 | const keys = [ 136 | { 137 | pubkey: payer, 138 | isSigner: true, 139 | isWritable: true, 140 | }, 141 | { 142 | pubkey: associatedTokenAddress, 143 | isSigner: false, 144 | isWritable: true, 145 | }, 146 | { 147 | pubkey: walletAddress, 148 | isSigner: false, 149 | isWritable: false, 150 | }, 151 | { 152 | pubkey: splTokenMintAddress, 153 | isSigner: false, 154 | isWritable: false, 155 | }, 156 | { 157 | pubkey: SystemProgram.programId, 158 | isSigner: false, 159 | isWritable: false, 160 | }, 161 | { 162 | pubkey: TOKEN_PROGRAM_ID, 163 | isSigner: false, 164 | isWritable: false, 165 | }, 166 | { 167 | pubkey: SYSVAR_RENT_PUBKEY, 168 | isSigner: false, 169 | isWritable: false, 170 | }, 171 | ]; 172 | instructions.push( 173 | new TransactionInstruction({ 174 | keys, 175 | programId: SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID, 176 | data: Buffer.from([]), 177 | }), 178 | ); 179 | } 180 | 181 | export function createMint( 182 | instructions: TransactionInstruction[], 183 | payer: PublicKey, 184 | mintRentExempt: number, 185 | decimals: number, 186 | owner: PublicKey, 187 | freezeAuthority: PublicKey, 188 | signers: Keypair[], 189 | ) { 190 | const account = createUninitializedMint( 191 | instructions, 192 | payer, 193 | mintRentExempt, 194 | signers, 195 | ); 196 | 197 | instructions.push( 198 | Token.createInitMintInstruction( 199 | TOKEN_PROGRAM_ID, 200 | account, 201 | decimals, 202 | owner, 203 | freezeAuthority, 204 | ), 205 | ); 206 | 207 | return account; 208 | } 209 | 210 | export function createTokenAccount( 211 | instructions: TransactionInstruction[], 212 | payer: PublicKey, 213 | accountRentExempt: number, 214 | mint: PublicKey, 215 | owner: PublicKey, 216 | signers: Keypair[], 217 | ) { 218 | const account = createUninitializedAccount( 219 | instructions, 220 | payer, 221 | accountRentExempt, 222 | signers, 223 | ); 224 | 225 | instructions.push( 226 | Token.createInitAccountInstruction(TOKEN_PROGRAM_ID, mint, account, owner), 227 | ); 228 | 229 | return account; 230 | } 231 | 232 | // export function ensureWrappedAccount( 233 | // instructions: TransactionInstruction[], 234 | // cleanupInstructions: TransactionInstruction[], 235 | // toCheck: TokenAccount | undefined, 236 | // payer: PublicKey, 237 | // amount: number, 238 | // signers: Keypair[], 239 | // ) { 240 | // if (toCheck && !toCheck.info.isNative) { 241 | // return toCheck.pubkey; 242 | // } 243 | 244 | // const TOKEN_PROGRAM_ID = programIds().token; 245 | // const account = Keypair.generate(); 246 | // instructions.push( 247 | // SystemProgram.createAccount({ 248 | // fromPubkey: payer, 249 | // newAccountPubkey: account.publicKey, 250 | // lamports: amount, 251 | // space: AccountLayout.span, 252 | // programId: TOKEN_PROGRAM_ID, 253 | // }), 254 | // ); 255 | 256 | // instructions.push( 257 | // Token.createInitAccountInstruction( 258 | // TOKEN_PROGRAM_ID, 259 | // WRAPPED_SOL_MINT, 260 | // account.publicKey, 261 | // payer, 262 | // ), 263 | // ); 264 | 265 | // cleanupInstructions.push( 266 | // Token.createCloseAccountInstruction( 267 | // TOKEN_PROGRAM_ID, 268 | // account.publicKey, 269 | // payer, 270 | // payer, 271 | // [], 272 | // ), 273 | // ); 274 | 275 | // signers.push(account); 276 | 277 | // return account.publicKey.toBase58(); 278 | // } 279 | 280 | // // TODO: check if one of to accounts needs to be native sol ... if yes unwrap it ... 281 | // export function findOrCreateAccountByMint( 282 | // payer: PublicKey, 283 | // owner: PublicKey, 284 | // instructions: TransactionInstruction[], 285 | // cleanupInstructions: TransactionInstruction[], 286 | // accountRentExempt: number, 287 | // mint: PublicKey, // use to identify same type 288 | // signers: Keypair[], 289 | // excluded?: Set, 290 | // ): PublicKey { 291 | // const accountToFind = mint.toBase58(); 292 | // const ownerKey = owner.toBase58(); 293 | // const account = cache 294 | // .byParser(TokenAccountParser) 295 | // .map(id => cache.get(id)) 296 | // .find( 297 | // acc => 298 | // acc !== undefined && 299 | // acc.info.mint.toBase58() === accountToFind && 300 | // acc.info.owner.toBase58() === ownerKey && 301 | // (excluded === undefined || !excluded.has(acc.pubkey)), 302 | // ); 303 | // const isWrappedSol = accountToFind === WRAPPED_SOL_MINT.toBase58(); 304 | 305 | // let toAccount: PublicKey; 306 | // if (account && !isWrappedSol) { 307 | // toAccount = new PublicKey(account.pubkey); 308 | // } else { 309 | // // creating depositor pool account 310 | // toAccount = createTokenAccount( 311 | // instructions, 312 | // payer, 313 | // accountRentExempt, 314 | // mint, 315 | // owner, 316 | // signers, 317 | // ); 318 | 319 | // if (isWrappedSol) { 320 | // cleanupInstructions.push( 321 | // Token.createCloseAccountInstruction( 322 | // TOKEN_PROGRAM_ID, 323 | // toAccount, 324 | // payer, 325 | // payer, 326 | // [], 327 | // ), 328 | // ); 329 | // } 330 | // } 331 | 332 | // return toAccount; 333 | // } 334 | -------------------------------------------------------------------------------- /public/js/pace.js: -------------------------------------------------------------------------------- 1 | /*! pace 1.0.0 */ 2 | (function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X=[].slice,Y={}.hasOwnProperty,Z=function(a,b){function c(){this.constructor=a}for(var d in b)Y.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},$=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};for(u={catchupTime:100,initialRate:.03,minTime:250,ghostTime:100,maxProgressPerFrame:20,easeFactor:1.25,startOnPageLoad:!0,restartOnPushState:!0,restartOnRequestAfter:500,target:"body",elements:{checkInterval:100,selectors:["body"]},eventLag:{minSamples:10,sampleCount:3,lagThreshold:3},ajax:{trackMethods:["GET"],trackWebSockets:!0,ignoreURLs:[]}},C=function(){var a;return null!=(a="undefined"!=typeof performance&&null!==performance&&"function"==typeof performance.now?performance.now():void 0)?a:+new Date},E=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,t=window.cancelAnimationFrame||window.mozCancelAnimationFrame,null==E&&(E=function(a){return setTimeout(a,50)},t=function(a){return clearTimeout(a)}),G=function(a){var b,c;return b=C(),(c=function(){var d;return d=C()-b,d>=33?(b=C(),a(d,function(){return E(c)})):setTimeout(c,33-d)})()},F=function(){var a,b,c;return c=arguments[0],b=arguments[1],a=3<=arguments.length?X.call(arguments,2):[],"function"==typeof c[b]?c[b].apply(c,a):c[b]},v=function(){var a,b,c,d,e,f,g;for(b=arguments[0],d=2<=arguments.length?X.call(arguments,1):[],f=0,g=d.length;g>f;f++)if(c=d[f])for(a in c)Y.call(c,a)&&(e=c[a],null!=b[a]&&"object"==typeof b[a]&&null!=e&&"object"==typeof e?v(b[a],e):b[a]=e);return b},q=function(a){var b,c,d,e,f;for(c=b=0,e=0,f=a.length;f>e;e++)d=a[e],c+=Math.abs(d),b++;return c/b},x=function(a,b){var c,d,e;if(null==a&&(a="options"),null==b&&(b=!0),e=document.querySelector("[data-pace-"+a+"]")){if(c=e.getAttribute("data-pace-"+a),!b)return c;try{return JSON.parse(c)}catch(f){return d=f,"undefined"!=typeof console&&null!==console?console.error("Error parsing inline pace options",d):void 0}}},g=function(){function a(){}return a.prototype.on=function(a,b,c,d){var e;return null==d&&(d=!1),null==this.bindings&&(this.bindings={}),null==(e=this.bindings)[a]&&(e[a]=[]),this.bindings[a].push({handler:b,ctx:c,once:d})},a.prototype.once=function(a,b,c){return this.on(a,b,c,!0)},a.prototype.off=function(a,b){var c,d,e;if(null!=(null!=(d=this.bindings)?d[a]:void 0)){if(null==b)return delete this.bindings[a];for(c=0,e=[];cQ;Q++)K=U[Q],D[K]===!0&&(D[K]=u[K]);i=function(a){function b(){return V=b.__super__.constructor.apply(this,arguments)}return Z(b,a),b}(Error),b=function(){function a(){this.progress=0}return a.prototype.getElement=function(){var a;if(null==this.el){if(a=document.querySelector(D.target),!a)throw new i;this.el=document.createElement("div"),this.el.className="pace pace-active",document.body.className=document.body.className.replace(/pace-done/g,""),document.body.className+=" pace-running",this.el.innerHTML='
\n
\n
\n
',null!=a.firstChild?a.insertBefore(this.el,a.firstChild):a.appendChild(this.el)}return this.el},a.prototype.finish=function(){var a;return a=this.getElement(),a.className=a.className.replace("pace-active",""),a.className+=" pace-inactive",document.body.className=document.body.className.replace("pace-running",""),document.body.className+=" pace-done"},a.prototype.update=function(a){return this.progress=a,this.render()},a.prototype.destroy=function(){try{this.getElement().parentNode.removeChild(this.getElement())}catch(a){i=a}return this.el=void 0},a.prototype.render=function(){var a,b,c,d,e,f,g;if(null==document.querySelector(D.target))return!1;for(a=this.getElement(),d="translate3d("+this.progress+"%, 0, 0)",g=["webkitTransform","msTransform","transform"],e=0,f=g.length;f>e;e++)b=g[e],a.children[0].style[b]=d;return(!this.lastRenderedProgress||this.lastRenderedProgress|0!==this.progress|0)&&(a.children[0].setAttribute("data-progress-text",""+(0|this.progress)+"%"),this.progress>=100?c="99":(c=this.progress<10?"0":"",c+=0|this.progress),a.children[0].setAttribute("data-progress",""+c)),this.lastRenderedProgress=this.progress},a.prototype.done=function(){return this.progress>=100},a}(),h=function(){function a(){this.bindings={}}return a.prototype.trigger=function(a,b){var c,d,e,f,g;if(null!=this.bindings[a]){for(f=this.bindings[a],g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(c.call(this,b));return g}},a.prototype.on=function(a,b){var c;return null==(c=this.bindings)[a]&&(c[a]=[]),this.bindings[a].push(b)},a}(),P=window.XMLHttpRequest,O=window.XDomainRequest,N=window.WebSocket,w=function(a,b){var c,d,e,f;f=[];for(d in b.prototype)try{e=b.prototype[d],f.push(null==a[d]&&"function"!=typeof e?a[d]=e:void 0)}catch(g){c=g}return f},A=[],j.ignore=function(){var a,b,c;return b=arguments[0],a=2<=arguments.length?X.call(arguments,1):[],A.unshift("ignore"),c=b.apply(null,a),A.shift(),c},j.track=function(){var a,b,c;return b=arguments[0],a=2<=arguments.length?X.call(arguments,1):[],A.unshift("track"),c=b.apply(null,a),A.shift(),c},J=function(a){var b;if(null==a&&(a="GET"),"track"===A[0])return"force";if(!A.length&&D.ajax){if("socket"===a&&D.ajax.trackWebSockets)return!0;if(b=a.toUpperCase(),$.call(D.ajax.trackMethods,b)>=0)return!0}return!1},k=function(a){function b(){var a,c=this;b.__super__.constructor.apply(this,arguments),a=function(a){var b;return b=a.open,a.open=function(d,e){return J(d)&&c.trigger("request",{type:d,url:e,request:a}),b.apply(a,arguments)}},window.XMLHttpRequest=function(b){var c;return c=new P(b),a(c),c};try{w(window.XMLHttpRequest,P)}catch(d){}if(null!=O){window.XDomainRequest=function(){var b;return b=new O,a(b),b};try{w(window.XDomainRequest,O)}catch(d){}}if(null!=N&&D.ajax.trackWebSockets){window.WebSocket=function(a,b){var d;return d=null!=b?new N(a,b):new N(a),J("socket")&&c.trigger("request",{type:"socket",url:a,protocols:b,request:d}),d};try{w(window.WebSocket,N)}catch(d){}}}return Z(b,a),b}(h),R=null,y=function(){return null==R&&(R=new k),R},I=function(a){var b,c,d,e;for(e=D.ajax.ignoreURLs,c=0,d=e.length;d>c;c++)if(b=e[c],"string"==typeof b){if(-1!==a.indexOf(b))return!0}else if(b.test(a))return!0;return!1},y().on("request",function(b){var c,d,e,f,g;return f=b.type,e=b.request,g=b.url,I(g)?void 0:j.running||D.restartOnRequestAfter===!1&&"force"!==J(f)?void 0:(d=arguments,c=D.restartOnRequestAfter||0,"boolean"==typeof c&&(c=0),setTimeout(function(){var b,c,g,h,i,k;if(b="socket"===f?e.readyState<2:0<(h=e.readyState)&&4>h){for(j.restart(),i=j.sources,k=[],c=0,g=i.length;g>c;c++){if(K=i[c],K instanceof a){K.watch.apply(K,d);break}k.push(void 0)}return k}},c))}),a=function(){function a(){var a=this;this.elements=[],y().on("request",function(){return a.watch.apply(a,arguments)})}return a.prototype.watch=function(a){var b,c,d,e;return d=a.type,b=a.request,e=a.url,I(e)?void 0:(c="socket"===d?new n(b):new o(b),this.elements.push(c))},a}(),o=function(){function a(a){var b,c,d,e,f,g,h=this;if(this.progress=0,null!=window.ProgressEvent)for(c=null,a.addEventListener("progress",function(a){return h.progress=a.lengthComputable?100*a.loaded/a.total:h.progress+(100-h.progress)/2},!1),g=["load","abort","timeout","error"],d=0,e=g.length;e>d;d++)b=g[d],a.addEventListener(b,function(){return h.progress=100},!1);else f=a.onreadystatechange,a.onreadystatechange=function(){var b;return 0===(b=a.readyState)||4===b?h.progress=100:3===a.readyState&&(h.progress=50),"function"==typeof f?f.apply(null,arguments):void 0}}return a}(),n=function(){function a(a){var b,c,d,e,f=this;for(this.progress=0,e=["error","open"],c=0,d=e.length;d>c;c++)b=e[c],a.addEventListener(b,function(){return f.progress=100},!1)}return a}(),d=function(){function a(a){var b,c,d,f;for(null==a&&(a={}),this.elements=[],null==a.selectors&&(a.selectors=[]),f=a.selectors,c=0,d=f.length;d>c;c++)b=f[c],this.elements.push(new e(b))}return a}(),e=function(){function a(a){this.selector=a,this.progress=0,this.check()}return a.prototype.check=function(){var a=this;return document.querySelector(this.selector)?this.done():setTimeout(function(){return a.check()},D.elements.checkInterval)},a.prototype.done=function(){return this.progress=100},a}(),c=function(){function a(){var a,b,c=this;this.progress=null!=(b=this.states[document.readyState])?b:100,a=document.onreadystatechange,document.onreadystatechange=function(){return null!=c.states[document.readyState]&&(c.progress=c.states[document.readyState]),"function"==typeof a?a.apply(null,arguments):void 0}}return a.prototype.states={loading:0,interactive:50,complete:100},a}(),f=function(){function a(){var a,b,c,d,e,f=this;this.progress=0,a=0,e=[],d=0,c=C(),b=setInterval(function(){var g;return g=C()-c-50,c=C(),e.push(g),e.length>D.eventLag.sampleCount&&e.shift(),a=q(e),++d>=D.eventLag.minSamples&&a=100&&(this.done=!0),b===this.last?this.sinceLastUpdate+=a:(this.sinceLastUpdate&&(this.rate=(b-this.last)/this.sinceLastUpdate),this.catchup=(b-this.progress)/D.catchupTime,this.sinceLastUpdate=0,this.last=b),b>this.progress&&(this.progress+=this.catchup*a),c=1-Math.pow(this.progress/100,D.easeFactor),this.progress+=c*this.rate*a,this.progress=Math.min(this.lastProgress+D.maxProgressPerFrame,this.progress),this.progress=Math.max(0,this.progress),this.progress=Math.min(100,this.progress),this.lastProgress=this.progress,this.progress},a}(),L=null,H=null,r=null,M=null,p=null,s=null,j.running=!1,z=function(){return D.restartOnPushState?j.restart():void 0},null!=window.history.pushState&&(T=window.history.pushState,window.history.pushState=function(){return z(),T.apply(window.history,arguments)}),null!=window.history.replaceState&&(W=window.history.replaceState,window.history.replaceState=function(){return z(),W.apply(window.history,arguments)}),l={ajax:a,elements:d,document:c,eventLag:f},(B=function(){var a,c,d,e,f,g,h,i;for(j.sources=L=[],g=["ajax","elements","document","eventLag"],c=0,e=g.length;e>c;c++)a=g[c],D[a]!==!1&&L.push(new l[a](D[a]));for(i=null!=(h=D.extraSources)?h:[],d=0,f=i.length;f>d;d++)K=i[d],L.push(new K(D));return j.bar=r=new b,H=[],M=new m})(),j.stop=function(){return j.trigger("stop"),j.running=!1,r.destroy(),s=!0,null!=p&&("function"==typeof t&&t(p),p=null),B()},j.restart=function(){return j.trigger("restart"),j.stop(),j.start()},j.go=function(){var a;return j.running=!0,r.render(),a=C(),s=!1,p=G(function(b,c){var d,e,f,g,h,i,k,l,n,o,p,q,t,u,v,w;for(l=100-r.progress,e=p=0,f=!0,i=q=0,u=L.length;u>q;i=++q)for(K=L[i],o=null!=H[i]?H[i]:H[i]=[],h=null!=(w=K.elements)?w:[K],k=t=0,v=h.length;v>t;k=++t)g=h[k],n=null!=o[k]?o[k]:o[k]=new m(g),f&=n.done,n.done||(e++,p+=n.tick(b));return d=p/e,r.update(M.tick(b,d)),r.done()||f||s?(r.update(100),j.trigger("done"),setTimeout(function(){return r.finish(),j.running=!1,j.trigger("hide")},Math.max(D.ghostTime,Math.max(D.minTime-(C()-a),0)))):c()})},j.start=function(a){v(D,a),j.running=!0;try{r.render()}catch(b){i=b}return document.querySelector(".pace")?(j.trigger("start"),j.go()):setTimeout(j.start,50)},"function"==typeof define&&define.amd?define(function(){return j}):"object"==typeof exports?module.exports=j:D.startOnPageLoad&&j.start()}).call(this); 3 | 4 | !function(e){e.fn.parallaxie=function(o){o=e.extend({speed:.2,repeat:"no-repeat",size:"cover",pos_x:"center",offset:0},o);return this.each(function(){var a=e(this),t=a.data("parallaxie");"object"!=typeof t&&(t={}),t=e.extend({},o,t);var s=a.data("image");if(void 0===s){if(!(s=a.css("background-image")))return;var n=t.offset+(a.offset().top-e(window).scrollTop())*(1-t.speed);a.css({"background-image":s,"background-size":t.size,"background-repeat":t.repeat,"background-attachment":"fixed","background-position":t.pos_x+" "+n+"px"}),e(window).scroll(function(){var o=t.offset+(a.offset().top-e(window).scrollTop())*(1-t.speed);a.data("pos_y",o),a.css("background-position",t.pos_x+" "+o+"px")})}}),this}}(jQuery); -------------------------------------------------------------------------------- /src/utils/mx/contexts/connection.tsx: -------------------------------------------------------------------------------- 1 | import { sleep, useLocalStorageState } from '../utils/utils'; 2 | import { 3 | Keypair, 4 | Blockhash, 5 | clusterApiUrl, 6 | Commitment, 7 | Connection, 8 | RpcResponseAndContext, 9 | SignatureStatus, 10 | SimulatedTransactionResponse, 11 | Transaction, 12 | TransactionInstruction, 13 | TransactionSignature, 14 | } from '@solana/web3.js'; 15 | import React, { useContext, useEffect, useMemo, useState } from 'react'; 16 | import { notify } from '../utils/notifications'; 17 | import { 18 | TokenInfo, 19 | TokenListProvider, 20 | ENV as ChainId, 21 | } from '@solana/spl-token-registry'; 22 | 23 | export type ENV = 24 | | 'mainnet-beta' 25 | | 'mainnet-beta (Solana)' 26 | | 'mainnet-beta (Serum)' 27 | | 'testnet' 28 | | 'devnet' 29 | | 'localnet' 30 | | 'lending'; 31 | 32 | export const ENDPOINTS = [ 33 | { 34 | name: 'mainnet-beta' as ENV, 35 | endpoint: 'https://api.metaplex.solana.com/', 36 | ChainId: ChainId.MainnetBeta, 37 | }, 38 | { 39 | name: 'mainnet-beta (Solana)' as ENV, 40 | endpoint: 'https://api.mainnet-beta.solana.com', 41 | ChainId: ChainId.MainnetBeta, 42 | }, 43 | { 44 | name: 'mainnet-beta (Serum)' as ENV, 45 | endpoint: 'https://solana-api.projectserum.com/', 46 | ChainId: ChainId.MainnetBeta, 47 | }, 48 | { 49 | name: 'testnet' as ENV, 50 | endpoint: clusterApiUrl('testnet'), 51 | ChainId: ChainId.Testnet, 52 | }, 53 | { 54 | name: 'devnet' as ENV, 55 | endpoint: clusterApiUrl('devnet'), 56 | ChainId: ChainId.Devnet, 57 | }, 58 | ]; 59 | 60 | const DEFAULT = ENDPOINTS[0].endpoint; 61 | 62 | interface ConnectionConfig { 63 | connection: Connection; 64 | endpoint: string; 65 | env: ENV; 66 | setEndpoint: (val: string) => void; 67 | tokens: TokenInfo[]; 68 | tokenMap: Map; 69 | } 70 | 71 | const ConnectionContext = React.createContext({ 72 | endpoint: DEFAULT, 73 | setEndpoint: () => {}, 74 | connection: new Connection(DEFAULT, 'recent'), 75 | env: ENDPOINTS[0].name, 76 | tokens: [], 77 | tokenMap: new Map(), 78 | }); 79 | 80 | // export function ConnectionProvider({ children = undefined as any }) { 81 | // const [endpoint, setEndpoint] = useLocalStorageState( 82 | // 'connectionEndpoint', 83 | // ENDPOINTS[0].endpoint, 84 | // ); 85 | 86 | // const connection = useMemo( 87 | // () => new Connection(endpoint, 'recent'), 88 | // [endpoint], 89 | // ); 90 | 91 | // const env = 92 | // ENDPOINTS.find(end => end.endpoint === endpoint)?.name || ENDPOINTS[0].name; 93 | 94 | // const [tokens, setTokens] = useState([]); 95 | // const [tokenMap, setTokenMap] = useState>(new Map()); 96 | // useEffect(() => { 97 | // // fetch token files 98 | // new TokenListProvider().resolve().then(container => { 99 | // const list = container 100 | // .excludeByTag('nft') 101 | // .filterByChainId( 102 | // ENDPOINTS.find(end => end.endpoint === endpoint)?.ChainId || 103 | // ChainId.MainnetBeta, 104 | // ) 105 | // .getList(); 106 | 107 | // const knownMints = [...list].reduce((map, item) => { 108 | // map.set(item.address, item); 109 | // return map; 110 | // }, new Map()); 111 | 112 | // setTokenMap(knownMints); 113 | // setTokens(list); 114 | // }); 115 | // }, [env]); 116 | 117 | // setProgramIds(env); 118 | 119 | // // The websocket library solana/web3.js uses closes its websocket connection when the subscription list 120 | // // is empty after opening its first time, preventing subsequent subscriptions from receiving responses. 121 | // // This is a hack to prevent the list from every getting empty 122 | // useEffect(() => { 123 | // const id = connection.onAccountChange( 124 | // Keypair.generate().publicKey, 125 | // () => {}, 126 | // ); 127 | // return () => { 128 | // connection.removeAccountChangeListener(id); 129 | // }; 130 | // }, [connection]); 131 | 132 | // useEffect(() => { 133 | // const id = connection.onSlotChange(() => null); 134 | // return () => { 135 | // connection.removeSlotChangeListener(id); 136 | // }; 137 | // }, [connection]); 138 | 139 | // return ( 140 | // 150 | // {children} 151 | // 152 | // ); 153 | // } 154 | 155 | export function useConnection() { 156 | return useContext(ConnectionContext).connection as Connection; 157 | } 158 | 159 | export function useConnectionConfig() { 160 | const context = useContext(ConnectionContext); 161 | return { 162 | endpoint: context.endpoint, 163 | setEndpoint: context.setEndpoint, 164 | env: context.env, 165 | tokens: context.tokens, 166 | tokenMap: context.tokenMap, 167 | }; 168 | } 169 | 170 | export const getErrorForTransaction = async ( 171 | connection: Connection, 172 | txid: string, 173 | ) => { 174 | // wait for all confirmation before geting transaction 175 | await connection.confirmTransaction(txid, 'max'); 176 | 177 | const tx = await connection.getParsedConfirmedTransaction(txid); 178 | 179 | const errors: string[] = []; 180 | if (tx?.meta && tx.meta.logMessages) { 181 | tx.meta.logMessages.forEach(log => { 182 | const regex = /Error: (.*)/gm; 183 | let m; 184 | while ((m = regex.exec(log)) !== null) { 185 | // This is necessary to avoid infinite loops with zero-width matches 186 | if (m.index === regex.lastIndex) { 187 | regex.lastIndex++; 188 | } 189 | 190 | if (m.length > 1) { 191 | errors.push(m[1]); 192 | } 193 | } 194 | }); 195 | } 196 | 197 | return errors; 198 | }; 199 | 200 | export enum SequenceType { 201 | Sequential, 202 | Parallel, 203 | StopOnFailure, 204 | } 205 | 206 | export async function sendTransactionsWithManualRetry( 207 | connection: Connection, 208 | wallet: any, 209 | instructions: TransactionInstruction[][], 210 | signers: Keypair[][], 211 | ) { 212 | let stopPoint = 0; 213 | let tries = 0; 214 | let lastInstructionsLength = null; 215 | let toRemoveSigners: Record = {}; 216 | instructions = instructions.filter((instr, i) => { 217 | if (instr.length > 0) { 218 | return true; 219 | } else { 220 | toRemoveSigners[i] = true; 221 | return false; 222 | } 223 | }); 224 | let filteredSigners = signers.filter((_, i) => !toRemoveSigners[i]); 225 | 226 | while (stopPoint < instructions.length && tries < 3) { 227 | instructions = instructions.slice(stopPoint, instructions.length); 228 | filteredSigners = filteredSigners.slice(stopPoint, filteredSigners.length); 229 | 230 | if (instructions.length === lastInstructionsLength) tries = tries + 1; 231 | else tries = 0; 232 | 233 | try { 234 | if (instructions.length === 1) { 235 | await sendTransactionWithRetry( 236 | connection, 237 | wallet, 238 | instructions[0], 239 | filteredSigners[0], 240 | 'single', 241 | ); 242 | stopPoint = 1; 243 | } else { 244 | stopPoint = await sendTransactions( 245 | connection, 246 | wallet, 247 | instructions, 248 | filteredSigners, 249 | SequenceType.StopOnFailure, 250 | ); 251 | } 252 | } catch (e) { 253 | console.error(e); 254 | } 255 | console.log( 256 | 'Died on ', 257 | stopPoint, 258 | 'retrying from instruction', 259 | instructions[stopPoint], 260 | 'instructions length is', 261 | instructions.length, 262 | ); 263 | lastInstructionsLength = instructions.length; 264 | } 265 | } 266 | 267 | export const sendTransactions = async ( 268 | connection: Connection, 269 | wallet: any, 270 | instructionSet: TransactionInstruction[][], 271 | signersSet: Keypair[][], 272 | sequenceType: SequenceType = SequenceType.Parallel, 273 | commitment: Commitment = 'max', 274 | successCallback: (txid: string, ind: number) => void = (txid, ind) => {}, 275 | failCallback: (reason: string, ind: number) => boolean = (txid, ind) => false, 276 | ): Promise => { 277 | const unsignedTxns: Transaction[] = []; 278 | 279 | let block = await connection.getRecentBlockhash(commitment); 280 | 281 | for (let i = 0; i < instructionSet.length; i++) { 282 | const instructions = instructionSet[i]; 283 | const signers = signersSet[i]; 284 | 285 | if (instructions.length === 0) { 286 | continue; 287 | } 288 | 289 | let transaction = new Transaction(); 290 | instructions.forEach(instruction => transaction.add(instruction)); 291 | transaction.recentBlockhash = block.blockhash; 292 | transaction.setSigners( 293 | // fee payed by the wallet owner 294 | wallet.publicKey, 295 | ...signers.map(s => s.publicKey), 296 | ); 297 | 298 | if (signers.length > 0) { 299 | transaction.partialSign(...signers); 300 | } 301 | 302 | unsignedTxns.push(transaction); 303 | } 304 | 305 | const signedTxns = await wallet.signAllTransactions(unsignedTxns); 306 | 307 | const pendingTxns: Promise<{ txid: string; slot: number }>[] = []; 308 | 309 | let breakEarlyObject = { breakEarly: false, i: 0 }; 310 | console.log( 311 | 'Signed txns length', 312 | signedTxns.length, 313 | 'vs handed in length', 314 | instructionSet.length, 315 | ); 316 | for (let i = 0; i < signedTxns.length; i++) { 317 | const signedTxnPromise = sendSignedTransaction({ 318 | connection, 319 | signedTransaction: signedTxns[i], 320 | }); 321 | 322 | signedTxnPromise 323 | .then(({ txid, slot }) => { 324 | successCallback(txid, i); 325 | }) 326 | .catch(reason => { 327 | failCallback(signedTxns[i], i); 328 | if (sequenceType === SequenceType.StopOnFailure) { 329 | breakEarlyObject.breakEarly = true; 330 | breakEarlyObject.i = i; 331 | } 332 | }); 333 | 334 | if (sequenceType !== SequenceType.Parallel) { 335 | try { 336 | await signedTxnPromise; 337 | } catch (e) { 338 | console.log('Caught failure', e); 339 | if (breakEarlyObject.breakEarly) { 340 | console.log('Died on ', breakEarlyObject.i); 341 | return breakEarlyObject.i; // Return the txn we failed on by index 342 | } 343 | } 344 | } else { 345 | pendingTxns.push(signedTxnPromise); 346 | } 347 | } 348 | 349 | if (sequenceType !== SequenceType.Parallel) { 350 | await Promise.all(pendingTxns); 351 | } 352 | 353 | return signedTxns.length; 354 | }; 355 | 356 | // export const sendTransaction = async ( 357 | // connection: Connection, 358 | // wallet: any, 359 | // instructions: TransactionInstruction[], 360 | // signers: Keypair[], 361 | // awaitConfirmation = true, 362 | // commitment: Commitment = 'singleGossip', 363 | // includesFeePayer: boolean = false, 364 | // block?: BlockhashAndFeeCalculator, 365 | // ) => { 366 | // let transaction = new Transaction(); 367 | // instructions.forEach(instruction => transaction.add(instruction)); 368 | // transaction.recentBlockhash = ( 369 | // block || (await connection.getRecentBlockhash(commitment)) 370 | // ).blockhash; 371 | 372 | // if (includesFeePayer) { 373 | // transaction.setSigners(...signers.map(s => s.publicKey)); 374 | // } else { 375 | // transaction.setSigners( 376 | // // fee payed by the wallet owner 377 | // wallet.publicKey, 378 | // ...signers.map(s => s.publicKey), 379 | // ); 380 | // } 381 | 382 | // if (signers.length > 0) { 383 | // transaction.partialSign(...signers); 384 | // } 385 | // if (!includesFeePayer) { 386 | // transaction = await wallet.signTransaction(transaction); 387 | // } 388 | 389 | // const rawTransaction = transaction.serialize(); 390 | // let options = { 391 | // skipPreflight: true, 392 | // commitment, 393 | // }; 394 | 395 | // const txid = await connection.sendRawTransaction(rawTransaction, options); 396 | // let slot = 0; 397 | 398 | // if (awaitConfirmation) { 399 | // const confirmation = await awaitTransactionSignatureConfirmation( 400 | // txid, 401 | // DEFAULT_TIMEOUT, 402 | // connection, 403 | // commitment, 404 | // ); 405 | 406 | // if (!confirmation) 407 | // throw new Error('Timed out awaiting confirmation on transaction'); 408 | // slot = confirmation?.slot || 0; 409 | 410 | // if (confirmation?.err) { 411 | // const errors = await getErrorForTransaction(connection, txid); 412 | // notify({ 413 | // message: 'Transaction failed...', 414 | // description: ( 415 | // <> 416 | // {errors.map(err => ( 417 | //
{err}
418 | // ))} 419 | // 420 | // 421 | // ), 422 | // type: 'error', 423 | // }); 424 | 425 | // throw new Error( 426 | // `Raw transaction ${txid} failed (${JSON.stringify(status)})`, 427 | // ); 428 | // } 429 | // } 430 | 431 | // return { txid, slot }; 432 | // }; 433 | 434 | export const sendTransactionWithRetry = async ( 435 | connection: Connection, 436 | wallet: any, 437 | instructions: TransactionInstruction[], 438 | signers: Keypair[], 439 | commitment: Commitment = 'singleGossip', 440 | includesFeePayer: boolean = false, 441 | beforeSend?: () => void, 442 | ) => { 443 | let transaction = new Transaction(); 444 | instructions.forEach(instruction => transaction.add(instruction)); 445 | transaction.recentBlockhash = ( 446 | (await connection.getRecentBlockhash(commitment)) 447 | ).blockhash; 448 | 449 | if (includesFeePayer) { 450 | transaction.setSigners(...signers.map(s => s.publicKey)); 451 | } else { 452 | transaction.setSigners( 453 | // fee payed by the wallet owner 454 | wallet.publicKey, 455 | ...signers.map(s => s.publicKey), 456 | ); 457 | } 458 | console.log(transaction) 459 | 460 | if (signers.length > 0) { 461 | transaction.partialSign(...signers); 462 | } 463 | if (!includesFeePayer) { 464 | transaction = await wallet.signTransaction(transaction); 465 | } 466 | 467 | if (beforeSend) { 468 | beforeSend(); 469 | } 470 | 471 | const { txid, slot } = await sendSignedTransaction({ 472 | connection, 473 | signedTransaction: transaction, 474 | }); 475 | 476 | return { txid, slot }; 477 | }; 478 | 479 | export const getUnixTs = () => { 480 | return new Date().getTime() / 1000; 481 | }; 482 | 483 | const DEFAULT_TIMEOUT = 15000; 484 | 485 | export async function sendSignedTransaction({ 486 | signedTransaction, 487 | connection, 488 | timeout = DEFAULT_TIMEOUT, 489 | }: { 490 | signedTransaction: Transaction; 491 | connection: Connection; 492 | sendingMessage?: string; 493 | sentMessage?: string; 494 | successMessage?: string; 495 | timeout?: number; 496 | }): Promise<{ txid: string; slot: number }> { 497 | const rawTransaction = signedTransaction.serialize(); 498 | const startTime = getUnixTs(); 499 | let slot = 0; 500 | const txid: TransactionSignature = await connection.sendRawTransaction( 501 | rawTransaction, 502 | { 503 | skipPreflight: true, 504 | }, 505 | ); 506 | 507 | console.log('Started awaiting confirmation for', txid); 508 | 509 | let done = false; 510 | (async () => { 511 | while (!done && getUnixTs() - startTime < timeout) { 512 | connection.sendRawTransaction(rawTransaction, { 513 | skipPreflight: true, 514 | }); 515 | await sleep(500); 516 | } 517 | })(); 518 | try { 519 | const confirmation = await awaitTransactionSignatureConfirmation( 520 | txid, 521 | timeout, 522 | connection, 523 | 'recent', 524 | true, 525 | ); 526 | 527 | if (!confirmation) 528 | throw new Error('Timed out awaiting confirmation on transaction'); 529 | 530 | if (confirmation.err) { 531 | console.error(confirmation.err); 532 | throw new Error('Transaction failed: Custom instruction error'); 533 | } 534 | 535 | slot = confirmation?.slot || 0; 536 | } catch (err) { 537 | console.error('Timeout Error caught', err); 538 | let simulateResult: SimulatedTransactionResponse | null = null; 539 | try { 540 | simulateResult = ( 541 | await simulateTransaction(connection, signedTransaction, 'single') 542 | ).value; 543 | } catch (e) {} 544 | if (simulateResult && simulateResult.err) { 545 | if (simulateResult.logs) { 546 | for (let i = simulateResult.logs.length - 1; i >= 0; --i) { 547 | const line = simulateResult.logs[i]; 548 | if (line.startsWith('Program log: ')) { 549 | throw new Error( 550 | 'Transaction failed: ' + line.slice('Program log: '.length), 551 | ); 552 | } 553 | } 554 | } 555 | throw new Error(JSON.stringify(simulateResult.err)); 556 | } 557 | // throw new Error('Transaction failed'); 558 | } finally { 559 | done = true; 560 | } 561 | 562 | console.log('Latency', txid, getUnixTs() - startTime); 563 | return { txid, slot }; 564 | } 565 | 566 | async function simulateTransaction( 567 | connection: Connection, 568 | transaction: Transaction, 569 | commitment: Commitment, 570 | ): Promise> { 571 | // @ts-ignore 572 | transaction.recentBlockhash = await connection._recentBlockhash( 573 | // @ts-ignore 574 | connection._disableBlockhashCaching, 575 | ); 576 | 577 | const signData = transaction.serializeMessage(); 578 | // @ts-ignore 579 | const wireTransaction = transaction._serialize(signData); 580 | const encodedTransaction = wireTransaction.toString('base64'); 581 | const config: any = { encoding: 'base64', commitment }; 582 | const args = [encodedTransaction, config]; 583 | 584 | // @ts-ignore 585 | const res = await connection._rpcRequest('simulateTransaction', args); 586 | if (res.error) { 587 | throw new Error('failed to simulate transaction: ' + res.error.message); 588 | } 589 | return res.result; 590 | } 591 | 592 | async function awaitTransactionSignatureConfirmation( 593 | txid: TransactionSignature, 594 | timeout: number, 595 | connection: Connection, 596 | commitment: Commitment = 'recent', 597 | queryStatus = false, 598 | ): Promise { 599 | let done = false; 600 | let status: SignatureStatus | null | void = { 601 | slot: 0, 602 | confirmations: 0, 603 | err: null, 604 | }; 605 | let subId = 0; 606 | status = await new Promise(async (resolve, reject) => { 607 | setTimeout(() => { 608 | if (done) { 609 | return; 610 | } 611 | done = true; 612 | console.log('Rejecting for timeout...'); 613 | reject({ timeout: true }); 614 | }, timeout); 615 | try { 616 | subId = connection.onSignature( 617 | txid, 618 | (result, context) => { 619 | done = true; 620 | status = { 621 | err: result.err, 622 | slot: context.slot, 623 | confirmations: 0, 624 | }; 625 | if (result.err) { 626 | console.log('Rejected via websocket', result.err); 627 | reject(status); 628 | } else { 629 | console.log('Resolved via websocket', result); 630 | resolve(status); 631 | } 632 | }, 633 | commitment, 634 | ); 635 | } catch (e) { 636 | done = true; 637 | console.error('WS error in setup', txid, e); 638 | } 639 | while (!done && queryStatus) { 640 | // eslint-disable-next-line no-loop-func 641 | (async () => { 642 | try { 643 | const signatureStatuses = await connection.getSignatureStatuses([ 644 | txid, 645 | ]); 646 | status = signatureStatuses && signatureStatuses.value[0]; 647 | if (!done) { 648 | if (!status) { 649 | console.log('REST null result for', txid, status); 650 | } else if (status.err) { 651 | console.log('REST error for', txid, status); 652 | done = true; 653 | reject(status.err); 654 | } else if (!status.confirmations) { 655 | console.log('REST no confirmations for', txid, status); 656 | } else { 657 | console.log('REST confirmation for', txid, status); 658 | done = true; 659 | resolve(status); 660 | } 661 | } 662 | } catch (e) { 663 | if (!done) { 664 | console.log('REST connection error: txid', txid, e); 665 | } 666 | } 667 | })(); 668 | await sleep(2000); 669 | } 670 | }); 671 | 672 | //@ts-ignore 673 | if (connection._signatureSubscriptions[subId]) 674 | connection.removeSignatureListener(subId); 675 | done = true; 676 | console.log('Returning status', status); 677 | return status; 678 | } 679 | -------------------------------------------------------------------------------- /public/css/style.min.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: balonkuregular; 3 | src: url(../fonts/BalonkuRegular-la1.woff) format('woff'); 4 | font-weight: 400; 5 | font-style: normal 6 | } 7 | 8 | @font-face { 9 | font-family: CutiePatootie-Rgjv; 10 | src: url(../fonts/Rajdhani-Regular.woff) format('woff'); 11 | font-weight: 700; 12 | font-style: bold; 13 | } 14 | 15 | .mb-50 { 16 | margin-bottom: 50px !important 17 | } 18 | 19 | .pt-50 { 20 | padding-top: 50px !important 21 | } 22 | 23 | .pb-50 { 24 | padding-bottom: 50px !important 25 | } 26 | 27 | body, 28 | html { 29 | -moz-osx-font-smoothing: grayscale; 30 | -webkit-font-smoothing: antialiased; 31 | -moz-font-smoothing: antialiased; 32 | font-smoothing: antialiased 33 | } 34 | 35 | * { 36 | margin: 0; 37 | padding: 0; 38 | -webkit-box-sizing: border-box; 39 | box-sizing: border-box; 40 | outline: 0; 41 | list-style: none; 42 | word-wrap: break-word 43 | } 44 | 45 | body { 46 | font-family: balonkuregular, CutiePatootie-Rgjv sans-serif; 47 | line-height: 1.75em; 48 | overflow-x: hidden !important; 49 | color: #fff 50 | } 51 | 52 | #roadmap, 53 | .about-buro, 54 | .accordion-box .block { 55 | background: rgba(0, 0, 0, .4); 56 | box-shadow: 5px 5px 32px 0 rgba(44, 44, 44, .3); 57 | backdrop-filter: blur(5px); 58 | } 59 | 60 | .about-buro2 { 61 | background: rgba(0, 0, 0, .8); 62 | box-shadow: 5px 5px 32px 0 rgba(44, 44, 44, .3); 63 | backdrop-filter: blur(5px); 64 | } 65 | 66 | .about-buro3 { 67 | background: rgba(0, 0, 0, .8); 68 | box-shadow: 5px 5px 32px 0 rgba(44, 44, 44, .3); 69 | backdrop-filter: blur(5px); 70 | } 71 | 72 | .video-bg { 73 | position: fixed; 74 | right: 0; 75 | top: 0; 76 | width: 100%; 77 | height: 100% 78 | } 79 | 80 | .video-bg video { 81 | width: 100%; 82 | height: 100%; 83 | object-fit: cover 84 | } 85 | 86 | p { 87 | font-family: CutiePatootie-Rgjv, sans-serif; 88 | padding: 20px; 89 | font-size: 28px; 90 | line-height: 1.75em; 91 | color: #fff; 92 | margin-bottom: 20px; 93 | letter-spacing: 1px 94 | } 95 | 96 | h1, 97 | h2, 98 | h4, 99 | h5, 100 | h6 { 101 | font-family: balonkuregular, sans-serif; 102 | font-weight: 400; 103 | line-height: 1.25em; 104 | margin: 0 0 20px 0 105 | } 106 | 107 | img { 108 | width: 100%; 109 | height: auto 110 | } 111 | 112 | img { 113 | -webkit-transition: all .5s; 114 | -o-transition: all .5s; 115 | transition: all .5s 116 | } 117 | 118 | a, 119 | a:hover, 120 | span { 121 | display: inline-block; 122 | text-decoration: none; 123 | color: inherit; 124 | font-family: inherit 125 | } 126 | 127 | b { 128 | font-weight: 400; 129 | color: #b19777 130 | } 131 | 132 | .o-hidden { 133 | overflow: hidden 134 | } 135 | 136 | .position-re { 137 | position: relative 138 | } 139 | 140 | .full-width { 141 | width: 100% 142 | } 143 | 144 | .bg-img { 145 | background-size: cover; 146 | background-repeat: no-repeat 147 | } 148 | 149 | .bg-fixed { 150 | background-attachment: fixed 151 | } 152 | 153 | .count { 154 | font-family: balonkuregular, sans-serif 155 | } 156 | 157 | .valign { 158 | display: -webkit-box; 159 | display: -ms-flexbox; 160 | display: flex; 161 | -webkit-box-align: center; 162 | -ms-flex-align: center; 163 | align-items: center 164 | } 165 | 166 | .v-middle { 167 | position: absolute; 168 | width: 100%; 169 | top: 50%; 170 | left: 0; 171 | -webkit-transform: translate(0, -50%); 172 | transform: translate(0, -50%) 173 | } 174 | 175 | .js .animate-box { 176 | opacity: 0; 177 | margin-bottom: 15px; 178 | } 179 | 180 | ::-webkit-selection { 181 | color: #fff; 182 | background: rgba(43, 30, 30, .2) 183 | } 184 | 185 | ::-moz-selection { 186 | color: #fff; 187 | background: rgba(43, 30, 30, .2) 188 | } 189 | 190 | ::selection { 191 | color: #fff; 192 | background: rgba(43, 30, 30, .2) 193 | } 194 | 195 | .section-padding { 196 | padding: 90px 0 197 | } 198 | 199 | .section-padding2 { 200 | padding: 0 0 90px 0 201 | } 202 | 203 | .section-padding h6 { 204 | color: #b19777; 205 | font-size: 20px; 206 | margin-bottom: 20px 207 | } 208 | 209 | .section-title { 210 | font-size: 32px; 211 | font-family: balonkuregular, sans-serif; 212 | font-weight: 400; 213 | color: #fff; 214 | text-transform: uppercase; 215 | position: relative; 216 | letter-spacing: 4px; 217 | word-spacing: 5px; 218 | /* margin-bottom: 30px */ 219 | } 220 | 221 | .section-title span { 222 | color: #ff0 223 | } 224 | 225 | .section-title2 { 226 | font-size: 35px; 227 | font-weight: 300; 228 | color: #b19777; 229 | position: relative; 230 | line-height: 1.25em; 231 | margin-bottom: 30px; 232 | letter-spacing: 3px; 233 | text-transform: uppercase 234 | } 235 | 236 | .navbar { 237 | position: absolute; 238 | left: 0; 239 | top: 0; 240 | width: 100%; 241 | z-index: 99; 242 | padding-right: 10%; 243 | padding-left: 0; 244 | padding-top: 0; 245 | padding-bottom: 0 246 | } 247 | 248 | .navbar .icon-bar { 249 | color: #fff 250 | } 251 | 252 | .navbar .navbar-nav .nav-link { 253 | font-family: balonkuregular, sans-serif; 254 | font-size: 15px; 255 | font-weight: 300; 256 | color: #fff; 257 | text-transform: uppercase; 258 | letter-spacing: 4px; 259 | margin: 5px 5px; 260 | -webkit-transition: all .4s; 261 | transition: all .4s 262 | } 263 | 264 | .navbar .navbar-nav .nav-link.black-color { 265 | color: #fff 266 | } 267 | 268 | .navbar .navbar-nav .nav-link:hover { 269 | color: #b19777 270 | } 271 | 272 | .navbar .navbar-nav .active { 273 | color: #b19777 !important 274 | } 275 | 276 | .nav-scroll { 277 | background-image: linear-gradient(to right, rgba(0, 0, 255, .2), rgba(238, 130, 238, .2)); 278 | box-shadow: 0 8px 32px 0 rgba(31, 38, 135, .37); 279 | backdrop-filter: blur(15px); 280 | -webkit-backdrop-filter: blur(15px); 281 | padding: 0 10% 0 0; 282 | position: fixed; 283 | top: -100px; 284 | left: 0; 285 | width: 100%; 286 | -webkit-transition: -webkit-transform .5s; 287 | transition: -webkit-transform .5s; 288 | transition: transform .5s; 289 | transition: transform .5s, -webkit-transform .5s; 290 | -webkit-transform: translateY(100px); 291 | transform: translateY(100px); 292 | -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .1); 293 | box-shadow: 0 5px 15px rgba(0, 0, 0, .1) 294 | } 295 | 296 | .nav-scroll .icon-bar { 297 | color: #fff 298 | } 299 | 300 | .nav-scroll .navbar-nav .nav-link { 301 | color: #fff 302 | } 303 | 304 | .nav-scroll .navbar-nav .active { 305 | color: #b19777 !important 306 | } 307 | 308 | .nav-scroll .navbar-nav .logo { 309 | padding: 15px 0; 310 | color: #999 311 | } 312 | 313 | .nav-scroll .logo { 314 | /* width: 100px */ 315 | } 316 | 317 | .nav-scroll .logo-img { 318 | margin-bottom: 0 319 | } 320 | 321 | .nav-scroll .logo-wrapper .logo h2 { 322 | font-family: balonkuregular, sans-serif; 323 | font-size: 40px; 324 | font-weight: 400; 325 | margin-bottom: 0; 326 | display: block; 327 | width: 100%; 328 | position: relative; 329 | line-height: 1.25em; 330 | letter-spacing: 5px; 331 | display: none 332 | } 333 | 334 | .nav-scroll .logo-wrapper .logo span { 335 | display: block; 336 | font-family: balonkuregular, sans-serif; 337 | font-size: 13px; 338 | font-weight: 400; 339 | letter-spacing: 3px; 340 | display: block; 341 | margin-top: 3px; 342 | line-height: 1.2em; 343 | text-transform: uppercase; 344 | margin-left: 5px; 345 | display: none !important 346 | } 347 | 348 | .nav-scroll .logo-wrapper { 349 | padding: 15px 70px 15px 150px 350 | } 351 | 352 | .logo-wrapper { 353 | float: left; 354 | padding: 30px 50px 355 | } 356 | 357 | .logo-wrapper .logo h2 { 358 | font-family: balonkuregular, sans-serif; 359 | font-size: 45px; 360 | font-weight: 400; 361 | display: block; 362 | width: 100%; 363 | position: relative; 364 | color: #ff0; 365 | letter-spacing: 9px; 366 | margin-bottom: 0 367 | } 368 | 369 | .logo-wrapper .logo h2 a i { 370 | color: #fff; 371 | font-size: 20px; 372 | vertical-align: super 373 | } 374 | 375 | .logo-wrapper .logo span { 376 | display: block; 377 | font-family: balonkuregular, sans-serif; 378 | font-size: 12px; 379 | color: #fff; 380 | font-weight: 400; 381 | letter-spacing: 4px; 382 | display: block; 383 | margin-top: 5px; 384 | line-height: 1.5em; 385 | text-transform: uppercase 386 | } 387 | 388 | .logo { 389 | padding: 20px 0 0 0; 390 | /* width: 150px; */ 391 | text-align: center 392 | } 393 | 394 | .logo-img { 395 | width: 270px; 396 | margin-bottom: 5px 397 | } 398 | 399 | @media screen and (max-width:767px) { 400 | .about-buro2 { 401 | backdrop-filter: none!important; 402 | } 403 | .about-buro3 { 404 | backdrop-filter: none!important; 405 | } 406 | .navbar { 407 | padding-right: 0; 408 | padding-right: 0 409 | } 410 | 411 | .logo-wrapper { 412 | float: left; 413 | padding: 15px 414 | } 415 | 416 | .nav-scroll .logo-wrapper { 417 | padding: 15px 418 | } 419 | 420 | .logo-img { 421 | width: 135px!important; 422 | } 423 | 424 | .roadmap { 425 | padding: 30px 35px!important; 426 | } 427 | 428 | .roadmap .point { 429 | padding: 10px 15px!important; 430 | } 431 | 432 | .test { 433 | right: 0; 434 | position: absolute; 435 | display: flex; 436 | flex-direction: column; 437 | align-items: end; 438 | padding: 0; 439 | top: 25%; 440 | } 441 | 442 | .section-title { 443 | font-size: 20px; 444 | } 445 | } 446 | 447 | .header { 448 | min-height: 100vh; 449 | overflow: hidden 450 | } 451 | 452 | .header .caption .o-hidden { 453 | display: block 454 | } 455 | 456 | .header .caption h1 { 457 | position: relative; 458 | margin-bottom: 20px; 459 | font-family: balonkuregular, sans-serif; 460 | font-size: 48px; 461 | text-transform: uppercase; 462 | line-height: 1.35em; 463 | -webkit-animation-delay: .4s; 464 | animation-delay: .4s; 465 | color: #fff; 466 | font-weight: 400; 467 | letter-spacing: 15px 468 | } 469 | 470 | .header .caption p span { 471 | letter-spacing: 5px; 472 | text-transform: uppercase; 473 | margin: 0 5px; 474 | padding-right: 14px; 475 | position: relative 476 | } 477 | 478 | .header .caption p span:last-child:after { 479 | display: none 480 | } 481 | 482 | .header .caption p span:after { 483 | content: ''; 484 | width: 7px; 485 | height: 7px; 486 | border-radius: 50%; 487 | background: #272727; 488 | position: absolute; 489 | top: 10px; 490 | right: 0; 491 | opacity: .5 492 | } 493 | 494 | .header .caption .butn-light { 495 | -webkit-animation-delay: .8s; 496 | animation-delay: .8s; 497 | margin-right: 15px 498 | } 499 | 500 | .header .caption .butn-lightt { 501 | -webkit-animation-delay: .8s; 502 | animation-delay: .8s; 503 | margin-right: 15px 504 | } 505 | 506 | .slider .owl-item, 507 | .slider-fade .owl-item { 508 | height: 100vh; 509 | position: relative 510 | } 511 | 512 | .slider .item, 513 | .slider-fade .item { 514 | position: absolute; 515 | top: 0; 516 | left: 0; 517 | height: 100%; 518 | width: 100%; 519 | background-size: cover; 520 | background-position: center 521 | } 522 | 523 | .slider .item .caption, 524 | .slider-fade .item .caption { 525 | z-index: 9 526 | } 527 | 528 | .owl-nav { 529 | display: none 530 | } 531 | 532 | .about { 533 | padding-bottom: 90px 534 | } 535 | 536 | .about .about-img img:hover { 537 | transform: scale(.95) 538 | } 539 | 540 | .about .about-img { 541 | position: relative; 542 | width: 85%; 543 | } 544 | 545 | .about .about-img .img { 546 | padding: 0 15px 30px 30px; 547 | position: relative 548 | } 549 | 550 | .about .about-img .img:before { 551 | content: ''; 552 | position: absolute; 553 | top: 30px; 554 | left: 0; 555 | right: 45px; 556 | bottom: 0; 557 | border: 1px solid #323232 558 | } 559 | 560 | .about .about-img .img img { 561 | position: relative; 562 | z-index: 2; 563 | background: #272727 564 | } 565 | 566 | .about-img-2 { 567 | position: relative 568 | } 569 | 570 | .about-img .about-img-2 { 571 | width: 85% !important; 572 | position: absolute; 573 | bottom: 0; 574 | right: 45px; 575 | z-index: 3; 576 | padding: 20px 15px; 577 | color: #fff; 578 | text-transform: uppercase; 579 | font-family: balonkuregular, sans-serif; 580 | font-weight: 300; 581 | letter-spacing: 7px; 582 | font-size: 26px; 583 | line-height: 1.5em; 584 | text-align: center; 585 | color: yellow; 586 | } 587 | 588 | .about-img-3 { 589 | position: relative 590 | } 591 | 592 | .about-img .about-img-3 { 593 | width: 85% !important; 594 | position: absolute; 595 | bottom: 0; 596 | right: 45px; 597 | z-index: 3; 598 | padding: 20px 15px; 599 | color: #fff; 600 | text-transform: uppercase; 601 | font-family: CutiePatootie-Rgjv; 602 | font-weight: 300; 603 | letter-spacing: 4px; 604 | font-size: 13px; 605 | line-height: 1.5em; 606 | text-align: center; 607 | color: lightgoldenrodyellow; 608 | } 609 | 610 | .projects .item { 611 | position: relative; 612 | overflow: hidden; 613 | margin-bottom: 30px; 614 | /* width: 80%; */ 615 | } 616 | 617 | .projects .item:hover img { 618 | -webkit-filter: none; 619 | filter: none; 620 | -webkit-transform: scale(1.09, 1.09); 621 | transform: scale(1.09, 1.09); 622 | -webkit-filter: brightness(70%); 623 | -webkit-transition: all 1s ease; 624 | -moz-transition: all 1s ease; 625 | -o-transition: all 1s ease; 626 | -ms-transition: all 1s ease; 627 | transition: all 1s ease 628 | } 629 | 630 | .projects .item:hover .con { 631 | bottom: 0 632 | } 633 | 634 | .projects .item img { 635 | -webkit-transition: all .5s; 636 | transition: all .5s; 637 | /* width: 80%; */ 638 | } 639 | 640 | .projects .item .con { 641 | position: absolute; 642 | bottom: -58px; 643 | left: 0; 644 | width: 100%; 645 | -webkit-transition: all .3s; 646 | transition: all .3s; 647 | z-index: 20 648 | } 649 | 650 | .projects .item .line { 651 | text-align: center; 652 | height: 1px; 653 | width: 60px; 654 | background-color: rgba(255, 255, 255, .2); 655 | transition-property: all; 656 | transition-duration: .3s; 657 | transition-timing-function: ease-in-out; 658 | margin: 0 auto 30px 659 | } 660 | 661 | .projects .item:hover .line { 662 | width: 100%; 663 | transition-property: all; 664 | transition-duration: .8s; 665 | transition-timing-function: ease-in-out 666 | } 667 | 668 | .butn-light { 669 | position: relative; 670 | line-height: 1.2em; 671 | cursor: pointer; 672 | } 673 | 674 | .butn-light a { 675 | font-weight: 300; 676 | font-family: balonkuregular, sans-serif; 677 | text-transform: uppercase; 678 | background: 0 0; 679 | color: #fff; 680 | padding: 12px 24px; 681 | margin: 15px; 682 | position: relative; 683 | font-size: 16px; 684 | letter-spacing: 3px; 685 | border: 1px solid #fff 686 | } 687 | 688 | .butn-light a:after { 689 | content: ''; 690 | width: 0; 691 | height: 100%; 692 | position: absolute; 693 | bottom: 0; 694 | left: 100%; 695 | z-index: 1; 696 | -webkit-transition: all .3s ease; 697 | transition: all .3s ease; 698 | background: #fff 699 | } 700 | 701 | .butn-light a span { 702 | position: relative; 703 | z-index: 2 704 | } 705 | 706 | .butn-light a:hover:after { 707 | width: 100%; 708 | left: 0; 709 | -webkit-transition: width .3s ease; 710 | transition: width .3s ease 711 | } 712 | 713 | .butn-light a:hover span { 714 | color: #272727 715 | } 716 | 717 | .butn-lightt { 718 | position: relative; 719 | line-height: 1.2em; 720 | cursor: pointer; 721 | } 722 | 723 | .butn-lightt a { 724 | font-weight: 300; 725 | font-family: balonkuregular, sans-serif; 726 | text-transform: uppercase; 727 | background: 0 0; 728 | color: #fff; 729 | padding: 12px 24px; 730 | margin: 15px; 731 | position: relative; 732 | font-size: 16px; 733 | letter-spacing: 3px; 734 | border: 1px solid #fff 735 | } 736 | 737 | .butn-lightt a:after { 738 | content: ''; 739 | width: 0; 740 | height: 100%; 741 | position: absolute; 742 | bottom: 0; 743 | left: 100%; 744 | z-index: 1; 745 | -webkit-transition: all .3s ease; 746 | transition: all .3s ease; 747 | background: #fff 748 | } 749 | 750 | .butn-lightt a span { 751 | position: relative; 752 | z-index: 2 753 | } 754 | 755 | .butn-lightt a:hover:after { 756 | width: 100%; 757 | left: 0; 758 | -webkit-transition: width .3s ease; 759 | transition: width .3s ease 760 | } 761 | 762 | .butn-lightt a:hover span { 763 | color: #272727 764 | } 765 | 766 | @media screen and (max-width:764px) { 767 | .butn-lightt { 768 | position: absolute; 769 | right: 0px; 770 | } 771 | .butn-lightt a { 772 | letter-spacing: 0!important; 773 | } 774 | 775 | /* .btn_wallt { 776 | position: absolute!important; 777 | right: 0px!important; 778 | } */ 779 | .btn_wallt { 780 | letter-spacing: 0!important; 781 | } 782 | .amount { 783 | display: none; 784 | } 785 | .mintAr { 786 | width: 100%!important; 787 | right: 0!important; 788 | } 789 | .totalMinted { 790 | display: block; 791 | } 792 | .about .about-img { 793 | position: initial!important; 794 | width: 100%!important; 795 | } 796 | } 797 | 798 | .hero-corner { 799 | top: 50px; 800 | right: 50px; 801 | z-index: 21; 802 | border-top: 1px solid; 803 | border-right: 1px solid 804 | } 805 | 806 | .hero-corner3 { 807 | bottom: 50px; 808 | right: 50px; 809 | border-bottom: 1px solid; 810 | border-right: 1px solid 811 | } 812 | 813 | .hero-corner4 { 814 | bottom: 50px; 815 | left: 50px; 816 | border-bottom: 1px solid; 817 | border-left: 1px solid 818 | } 819 | 820 | .hero-corner, 821 | .hero-corner3, 822 | .hero-corner4 { 823 | position: absolute; 824 | width: 70px; 825 | height: 70px; 826 | z-index: 21; 827 | border-color: rgba(255, 255, 255, .2) 828 | } 829 | 830 | .pace { 831 | pointer-events: none; 832 | -webkit-user-select: none; 833 | -moz-user-select: none; 834 | -ms-user-select: none; 835 | user-select: none; 836 | z-index: 99999999999999; 837 | position: fixed; 838 | margin: auto; 839 | top: 0; 840 | left: 0; 841 | right: 0; 842 | bottom: 0; 843 | width: 400px; 844 | border: 0; 845 | height: 1px; 846 | overflow: hidden; 847 | background: rgba(255, 255, 255, .05); 848 | -webkit-transition: all 1s; 849 | -o-transition: all 1s; 850 | transition: all 1s 851 | } 852 | 853 | .pace .pace-progress { 854 | -webkit-transform: translate3d(0, 0, 0); 855 | transform: translate3d(0, 0, 0); 856 | max-width: 300px; 857 | position: fixed; 858 | z-index: 99999999999999; 859 | display: block; 860 | position: absolute; 861 | top: 0; 862 | right: 100%; 863 | height: 100%; 864 | width: 100%; 865 | background: #b19777 866 | } 867 | 868 | .pace.pace-inactive { 869 | width: 100vw; 870 | opacity: 0 871 | } 872 | 873 | .pace.pace-inactive .pace-progress { 874 | max-width: 100vw 875 | } 876 | 877 | #preloader { 878 | width: 100%; 879 | height: 100vh; 880 | overflow: hidden; 881 | position: fixed; 882 | z-index: 9999999 883 | } 884 | 885 | #preloader:after, 886 | #preloader:before { 887 | content: ''; 888 | position: fixed; 889 | left: 0; 890 | height: 50%; 891 | width: 100%; 892 | background: #272727; 893 | -webkit-transition-timing-function: cubic-bezier(.19, 1, .22, 1); 894 | -o-transition-timing-function: cubic-bezier(.19, 1, .22, 1); 895 | transition-timing-function: cubic-bezier(.19, 1, .22, 1) 896 | } 897 | 898 | #preloader:before { 899 | top: 0 900 | } 901 | 902 | #preloader:after { 903 | bottom: 0 904 | } 905 | 906 | .accordion-box { 907 | position: relative 908 | } 909 | 910 | .accordion-box .block { 911 | position: relative; 912 | border-radius: 0; 913 | overflow: hidden; 914 | margin-bottom: 16px 915 | } 916 | 917 | .accordion-box .block:last-child { 918 | margin-bottom: 0 919 | } 920 | 921 | .accordion-box .block .acc-btn { 922 | position: relative; 923 | font-size: 20px; 924 | line-height: 27px; 925 | font-weight: 300; 926 | letter-spacing: 1px; 927 | cursor: pointer; 928 | padding: 20px 40px; 929 | padding-right: 60px; 930 | color: #fff; 931 | transition: all .5s ease; 932 | font-family: balonkuregular, sans-serif 933 | } 934 | 935 | .accordion-box .block .acc-btn .count { 936 | color: #b19777; 937 | padding-right: 3px 938 | } 939 | 940 | .accordion-box .block .acc-btn.active { 941 | color: #ff0; 942 | box-shadow: 0 1px 50px 0 rgba(0, 0, 0, .1) 943 | } 944 | 945 | .accordion-box .block .acc-content { 946 | position: relative; 947 | display: none 948 | } 949 | 950 | .accordion-box .block .content { 951 | position: relative; 952 | padding: 0 40px 30px; 953 | color: #fff 954 | } 955 | 956 | .accordion-box .block .acc-content.current { 957 | display: block 958 | } 959 | 960 | .comming { 961 | min-height: 100vh; 962 | height: auto; 963 | position: relative; 964 | background-blend-mode: overlay; 965 | background: rgba(255, 255, 255, .2); 966 | background-size: cover; 967 | background-position: center; 968 | background-attachment: fixed; 969 | color: #fff 970 | } 971 | 972 | .comming .item { 973 | background-color: rgba(0, 0, 0, .3); 974 | border: 1px solid rgba(255, 255, 255, .1); 975 | padding: 30px 15px; 976 | margin-bottom: 30px 977 | } 978 | 979 | .comming h6 { 980 | color: #ff0; 981 | font-size: 13px; 982 | font-family: balonkuregular, sans-serif; 983 | font-weight: 300; 984 | text-transform: uppercase; 985 | margin-bottom: 5px; 986 | letter-spacing: 5px; 987 | line-height: 1.5em 988 | } 989 | 990 | .comming h3 { 991 | font-size: 48px; 992 | line-height: 1.25em; 993 | font-family: balonkuregular, sans-serif; 994 | font-weight: 400; 995 | color: #fff; 996 | position: relative; 997 | text-transform: uppercase; 998 | letter-spacing: 3px; 999 | margin-bottom: 15px 1000 | } 1001 | 1002 | .comming h2 { 1003 | font-size: 48px; 1004 | line-height: 1.25em; 1005 | font-family: balonkuregular, sans-serif; 1006 | font-weight: 400; 1007 | color: #fff; 1008 | position: relative; 1009 | text-transform: uppercase; 1010 | letter-spacing: 15px; 1011 | margin-bottom: 20px; 1012 | margin-top: 20px 1013 | } 1014 | 1015 | .comming p { 1016 | color: #fff; 1017 | font-size: 16px 1018 | } 1019 | 1020 | .mobileMenu { 1021 | display: none; 1022 | } 1023 | 1024 | @media screen and (max-width:991px) { 1025 | .bg-fixed { 1026 | background-attachment: scroll !important 1027 | } 1028 | 1029 | .navbar .logo { 1030 | text-align: left; 1031 | margin-left: 0 1032 | } 1033 | 1034 | .nav-scroll .logo { 1035 | /* width: 150px */ 1036 | } 1037 | 1038 | .logo-img { 1039 | margin-bottom: 0 1040 | } 1041 | 1042 | .navbar button { 1043 | margin-right: 15px; 1044 | outline: 0 !important; 1045 | background: 0 0 1046 | } 1047 | 1048 | .navbar .container { 1049 | max-width: 100% 1050 | } 1051 | 1052 | .navbar .navbar-collapse { 1053 | max-height: 360px; 1054 | overflow: auto; 1055 | text-align: left; 1056 | padding: 15px 30px 30px 15px; 1057 | background: rgba(255, 255, 255, .2); 1058 | box-shadow: 0 8px 12px 0 rgba(31, 38, 135, .3); 1059 | backdrop-filter: blur(20px); 1060 | -webkit-backdrop-filter: blur(20px) 1061 | } 1062 | 1063 | .header { 1064 | background-attachment: scroll !important; 1065 | background-position: 50% 0 !important 1066 | } 1067 | 1068 | .hero-corner, 1069 | .hero-corner2, 1070 | .hero-corner3, 1071 | .hero-corner4 { 1072 | display: none 1073 | } 1074 | 1075 | .header .caption h1 { 1076 | font-size: 40px 1077 | } 1078 | } 1079 | 1080 | @media screen and (max-width:767px) { 1081 | .mobileMenuShow { 1082 | display: flex!important; 1083 | align-items: center; 1084 | justify-content: center; 1085 | position: relative; 1086 | width: 100%; 1087 | } 1088 | 1089 | .logo-wrapper .logo h2 { 1090 | display: none 1091 | } 1092 | 1093 | .header .caption h1 { 1094 | font-size: 30px; 1095 | margin-bottom: 15px; 1096 | letter-spacing: 10px; 1097 | line-height: 1.35em 1098 | } 1099 | 1100 | .header .caption p { 1101 | font-size: 15px; 1102 | margin-right: 10px 1103 | } 1104 | } 1105 | 1106 | @media screen and (max-width:480px) { 1107 | .section-head h4 { 1108 | font-size: 30px 1109 | } 1110 | 1111 | .text-left { 1112 | text-align: center 1113 | } 1114 | 1115 | .text-center { 1116 | text-align: center 1117 | } 1118 | 1119 | .text-right { 1120 | text-align: center 1121 | } 1122 | } 1123 | 1124 | .point-text p { 1125 | padding: 0; 1126 | line-height: 1 1127 | } 1128 | 1129 | .roadmap { 1130 | padding: 30px 50px 1131 | } 1132 | 1133 | .roadmap h3 { 1134 | color: #ff0 1135 | } 1136 | 1137 | .roadmap .point { 1138 | display: -webkit-box; 1139 | display: -ms-flexbox; 1140 | display: flex; 1141 | -webkit-box-orient: vertical; 1142 | -webkit-box-direction: normal; 1143 | -ms-flex-direction: column; 1144 | flex-direction: column; 1145 | padding: 10px 50px; 1146 | position: relative 1147 | } 1148 | 1149 | .roadmap .point:first-child .point-index { 1150 | top: auto; 1151 | bottom: 0; 1152 | -webkit-transform: translate(-50%, 2px) !important; 1153 | transform: translate(-50%, 2px) !important 1154 | } 1155 | 1156 | .roadmap .point:last-child .point-index { 1157 | top: 0; 1158 | -webkit-transform: translate(50%, -2px) !important; 1159 | transform: translate(50%, -2px) !important 1160 | } 1161 | 1162 | .roadmap .point:not(:last-child) { 1163 | border-bottom: 2px solid gold 1164 | } 1165 | 1166 | .roadmap .point:nth-child(odd) { 1167 | -webkit-box-align: start; 1168 | -ms-flex-align: start; 1169 | align-items: flex-start 1170 | } 1171 | 1172 | .roadmap .point:nth-child(odd):not(:first-child) { 1173 | border-left: 2px solid gold 1174 | } 1175 | 1176 | .roadmap .point:nth-child(odd) .point-index { 1177 | left: 0; 1178 | -webkit-transform: translate(-50%, -50%); 1179 | transform: translate(-50%, -50%) 1180 | } 1181 | 1182 | .roadmap .point:nth-child(even) { 1183 | -webkit-box-align: end; 1184 | -ms-flex-align: end; 1185 | align-items: flex-end 1186 | } 1187 | 1188 | .roadmap .point:nth-child(even):not(:last-child) { 1189 | border-right: 2px solid gold 1190 | } 1191 | 1192 | .roadmap .point:nth-child(even) .point-index { 1193 | right: 0; 1194 | -webkit-transform: translate(50%, -50%); 1195 | transform: translate(50%, -50%) 1196 | } 1197 | 1198 | .roadmap .point .point-index { 1199 | position: absolute; 1200 | top: 50%; 1201 | width: 40px; 1202 | height: 40px; 1203 | background: #151317; 1204 | border: 2px solid gold; 1205 | border-radius: 50%; 1206 | display: -webkit-box; 1207 | display: -ms-flexbox; 1208 | display: flex; 1209 | -webkit-box-align: center; 1210 | -ms-flex-align: center; 1211 | align-items: center; 1212 | -webkit-box-pack: center; 1213 | -ms-flex-pack: center; 1214 | justify-content: center; 1215 | font-size: 23px; 1216 | font-weight: 700 1217 | } 1218 | 1219 | .roadmap .point .point-label { 1220 | -webkit-box-flex: 1; 1221 | -ms-flex: 1 0 100%; 1222 | flex: 1 0 100%; 1223 | width: 100%; 1224 | font-size: 14px; 1225 | margin-bottom: 5px 1226 | } 1227 | 1228 | @media (min-width:641px) { 1229 | .roadmap .point .point-label { 1230 | -webkit-box-flex: 1; 1231 | -ms-flex: 1 0 50%; 1232 | flex: 1 0 50%; 1233 | width: 50% 1234 | } 1235 | } 1236 | 1237 | .roadmap .point .point-text { 1238 | -webkit-box-flex: 1; 1239 | -ms-flex: 1 0 100%; 1240 | flex: 1 0 100%; 1241 | width: 100%; 1242 | font-size: 12px; 1243 | color: #ccc 1244 | } 1245 | 1246 | @media (min-width:641px) { 1247 | .roadmap .point .point-text { 1248 | -webkit-box-flex: 1; 1249 | -ms-flex: 1 0 50%; 1250 | flex: 1 0 50%; 1251 | width: 50% 1252 | } 1253 | } 1254 | 1255 | .mintAddBtn { 1256 | border: 1px white solid; 1257 | padding: 0 7px; 1258 | border-radius: 5px; 1259 | margin: 0 15px; 1260 | cursor: pointer; 1261 | } 1262 | 1263 | .mintAr { 1264 | position: absolute; 1265 | z-index: 9; 1266 | text-align: center; 1267 | top: 48%; 1268 | background: rgb(7 32 52 / 90%); 1269 | padding: 45px; 1270 | border-radius: 55px; 1271 | width: 550px; 1272 | right: 10%; 1273 | } 1274 | 1275 | .point-text li { 1276 | list-style-type: disclosure-closed; 1277 | margin-left: 30px; 1278 | } 1279 | 1280 | /* .btn_wallet { 1281 | -webkit-animation-delay: .8s!important; 1282 | animation-delay: .8s!important; 1283 | margin-right: 15px!important; 1284 | position: relative!important; 1285 | line-height: 1.2em!important; 1286 | cursor: pointer!important; 1287 | 1288 | font-weight: 300!important; 1289 | font-family: balonkuregular, sans-serif!important; 1290 | text-transform: uppercase!important; 1291 | background: 0 0!important; 1292 | color: #fff!important; 1293 | padding: 12px 24px!important; 1294 | margin: 15px!important; 1295 | position: relative!important; 1296 | font-size: 16px!important; 1297 | letter-spacing: 3px!important; 1298 | border: 1px solid #fff!important; 1299 | } 1300 | 1301 | .btn_wallet:after { 1302 | content: ''!important; 1303 | width: 0!important; 1304 | height: 100%!important; 1305 | position: absolute!important; 1306 | bottom: 0!important; 1307 | left: 100%!important; 1308 | z-index: 1!important; 1309 | -webkit-transition: all .3s ease!important; 1310 | transition: all .3s ease!important; 1311 | background: #fff!important; 1312 | color: black!important; 1313 | } 1314 | 1315 | .btn_wallet { 1316 | position: relative; 1317 | z-index: 2 1318 | } 1319 | 1320 | .btn_wallet:hover:after { 1321 | width: 100%!important; 1322 | left: 0!important; 1323 | -webkit-transition: width .3s ease!important; 1324 | transition: width .3s ease!important; 1325 | } */ 1326 | 1327 | 1328 | .btn_wallet { 1329 | -webkit-animation-delay: .8s!important; 1330 | animation-delay: .8s!important; 1331 | margin-right: 15px!important; 1332 | } 1333 | 1334 | .btn_wallet { 1335 | position: relative!important; 1336 | line-height: 1.2em!important; 1337 | cursor: pointer!important; 1338 | } 1339 | 1340 | .btn_wallet { 1341 | font-weight: 300!important; 1342 | font-family: balonkuregular, sans-serif!important; 1343 | text-transform: uppercase!important; 1344 | background: 0 0!important; 1345 | color: #fff!important; 1346 | padding: 12px 24px!important; 1347 | margin: 15px!important; 1348 | position: relative!important; 1349 | font-size: 16px!important; 1350 | letter-spacing: 3px!important; 1351 | border: 1px solid #fff!important; 1352 | border-radius: 0px!important; 1353 | height: 100%!important; 1354 | } 1355 | 1356 | .btn_wallet:after { 1357 | content: ''!important; 1358 | width: 0!important; 1359 | height: 100%!important; 1360 | position: absolute!important; 1361 | bottom: 0!important; 1362 | left: 100%!important; 1363 | z-index: 1!important; 1364 | -webkit-transition: all .3s ease!important; 1365 | transition: all .3s ease!important; 1366 | background: rgba(255, 255, 255, 0.5)!important; 1367 | } 1368 | 1369 | .btn_wallet span { 1370 | position: relative!important; 1371 | z-index: 2!important; 1372 | } 1373 | 1374 | .btn_wallet:hover:after { 1375 | width: 100%!important; 1376 | left: 0!important; 1377 | -webkit-transition: width .3s ease!important; 1378 | transition: width .3s ease!important; 1379 | } 1380 | 1381 | .btn_wallet:hover { 1382 | /* color: #272727!important; */ 1383 | z-index: 2!important; 1384 | } 1385 | 1386 | .teamname { 1387 | display: block; 1388 | color: yellow; 1389 | } 1390 | 1391 | .btn_wallett { 1392 | -webkit-animation-delay: .8s!important; 1393 | animation-delay: .8s!important; 1394 | margin-right: 15px!important; 1395 | } 1396 | 1397 | .btn_wallett { 1398 | position: relative!important; 1399 | line-height: 1.2em!important; 1400 | cursor: pointer!important; 1401 | } 1402 | 1403 | .btn_wallett { 1404 | font-weight: 300!important; 1405 | font-family: balonkuregular, sans-serif!important; 1406 | text-transform: uppercase!important; 1407 | background: 0 0!important; 1408 | color: #fff!important; 1409 | padding: 12px 24px!important; 1410 | margin: 5px!important; 1411 | position: relative!important; 1412 | font-size: 16px!important; 1413 | letter-spacing: 3px!important; 1414 | border: 1px solid #fff!important; 1415 | border-radius: 0px!important; 1416 | height: 100%!important; 1417 | } 1418 | 1419 | .btn_wallett:after { 1420 | content: ''!important; 1421 | width: 0!important; 1422 | height: 100%!important; 1423 | position: absolute!important; 1424 | bottom: 0!important; 1425 | left: 100%!important; 1426 | z-index: 1!important; 1427 | -webkit-transition: all .3s ease!important; 1428 | transition: all .3s ease!important; 1429 | background: rgba(255, 255, 255, 0.5)!important; 1430 | } 1431 | 1432 | .btn_wallett span { 1433 | position: relative!important; 1434 | z-index: 2!important; 1435 | } 1436 | 1437 | .btn_wallett:hover:after { 1438 | width: 100%!important; 1439 | left: 0!important; 1440 | -webkit-transition: width .3s ease!important; 1441 | transition: width .3s ease!important; 1442 | } 1443 | 1444 | .btn_wallett:hover { 1445 | /* color: #272727!important; */ 1446 | z-index: 2!important; 1447 | } -------------------------------------------------------------------------------- /src/utils/mx/metadata.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublicKey, 3 | SystemProgram, 4 | SYSVAR_RENT_PUBKEY, 5 | TransactionInstruction, 6 | } from '@solana/web3.js'; 7 | import { programIds } from './utils/programIds'; 8 | import { deserializeUnchecked, serialize } from 'borsh'; 9 | import BN from 'bn.js'; 10 | import { findProgramAddress, StringPublicKey, toPublicKey } from './utils'; 11 | export const METADATA_PREFIX = 'metadata'; 12 | export const EDITION = 'edition'; 13 | export const RESERVATION = 'reservation'; 14 | 15 | export const MAX_NAME_LENGTH = 32; 16 | 17 | export const MAX_SYMBOL_LENGTH = 10; 18 | 19 | export const MAX_URI_LENGTH = 200; 20 | 21 | export const MAX_CREATOR_LIMIT = 5; 22 | 23 | export const MAX_CREATOR_LEN = 32 + 1 + 1; 24 | export const MAX_METADATA_LEN = 25 | 1 + 26 | 32 + 27 | 32 + 28 | MAX_NAME_LENGTH + 29 | MAX_SYMBOL_LENGTH + 30 | MAX_URI_LENGTH + 31 | MAX_CREATOR_LIMIT * MAX_CREATOR_LEN + 32 | 2 + 33 | 1 + 34 | 1 + 35 | 198; 36 | 37 | export const MAX_EDITION_LEN = 1 + 32 + 8 + 200; 38 | 39 | export const EDITION_MARKER_BIT_SIZE = 248; 40 | 41 | export enum MetadataKey { 42 | Uninitialized = 0, 43 | MetadataV1 = 4, 44 | EditionV1 = 1, 45 | MasterEditionV1 = 2, 46 | MasterEditionV2 = 6, 47 | EditionMarker = 7, 48 | } 49 | 50 | export enum MetadataCategory { 51 | Audio = 'audio', 52 | Video = 'video', 53 | Image = 'image', 54 | VR = 'vr', 55 | HTML = 'html', 56 | } 57 | 58 | export type MetadataFile = { 59 | uri: string; 60 | type: string; 61 | }; 62 | 63 | export type FileOrString = MetadataFile | string; 64 | 65 | export type Attribute = { 66 | trait_type?: string; 67 | display_type?: string; 68 | value: string | number; 69 | }; 70 | 71 | export interface IMetadataExtension { 72 | name: string; 73 | symbol: string; 74 | 75 | creators: Creator[] | null; 76 | description: string; 77 | // preview image absolute URI 78 | image: string; 79 | animation_url?: string; 80 | 81 | attributes?: Attribute[]; 82 | 83 | // stores link to item on meta 84 | external_url: string; 85 | 86 | seller_fee_basis_points: number; 87 | 88 | properties: { 89 | files?: FileOrString[]; 90 | category: MetadataCategory; 91 | maxSupply?: number; 92 | creators?: { 93 | address: string; 94 | shares: number; 95 | }[]; 96 | }; 97 | } 98 | 99 | export class MasterEditionV1 { 100 | key: MetadataKey; 101 | supply: BN; 102 | maxSupply?: BN; 103 | /// Can be used to mint tokens that give one-time permission to mint a single limited edition. 104 | printingMint: StringPublicKey; 105 | /// If you don't know how many printing tokens you are going to need, but you do know 106 | /// you are going to need some amount in the future, you can use a token from this mint. 107 | /// Coming back to token metadata with one of these tokens allows you to mint (one time) 108 | /// any number of printing tokens you want. This is used for instance by Auction Manager 109 | /// with participation NFTs, where we dont know how many people will bid and need participation 110 | /// printing tokens to redeem, so we give it ONE of these tokens to use after the auction is over, 111 | /// because when the auction begins we just dont know how many printing tokens we will need, 112 | /// but at the end we will. At the end it then burns this token with token-metadata to 113 | /// get the printing tokens it needs to give to bidders. Each bidder then redeems a printing token 114 | /// to get their limited editions. 115 | oneTimePrintingAuthorizationMint: StringPublicKey; 116 | 117 | constructor(args: { 118 | key: MetadataKey; 119 | supply: BN; 120 | maxSupply?: BN; 121 | printingMint: StringPublicKey; 122 | oneTimePrintingAuthorizationMint: StringPublicKey; 123 | }) { 124 | this.key = MetadataKey.MasterEditionV1; 125 | this.supply = args.supply; 126 | this.maxSupply = args.maxSupply; 127 | this.printingMint = args.printingMint; 128 | this.oneTimePrintingAuthorizationMint = 129 | args.oneTimePrintingAuthorizationMint; 130 | } 131 | } 132 | 133 | export class MasterEditionV2 { 134 | key: MetadataKey; 135 | supply: BN; 136 | maxSupply?: BN; 137 | 138 | constructor(args: { key: MetadataKey; supply: BN; maxSupply?: BN }) { 139 | this.key = MetadataKey.MasterEditionV2; 140 | this.supply = args.supply; 141 | this.maxSupply = args.maxSupply; 142 | } 143 | } 144 | 145 | export class EditionMarker { 146 | key: MetadataKey; 147 | ledger: number[]; 148 | 149 | constructor(args: { key: MetadataKey; ledger: number[] }) { 150 | this.key = MetadataKey.EditionMarker; 151 | this.ledger = args.ledger; 152 | } 153 | 154 | editionTaken(edition: number) { 155 | const editionOffset = edition % EDITION_MARKER_BIT_SIZE; 156 | const indexOffset = Math.floor(editionOffset / 8); 157 | 158 | if (indexOffset > 30) { 159 | throw Error('bad index for edition'); 160 | } 161 | 162 | const positionInBitsetFromRight = 7 - (editionOffset % 8); 163 | 164 | const mask = Math.pow(2, positionInBitsetFromRight); 165 | 166 | const appliedMask = this.ledger[indexOffset] & mask; 167 | 168 | return appliedMask != 0; 169 | } 170 | } 171 | 172 | export class Edition { 173 | key: MetadataKey; 174 | /// Points at MasterEdition struct 175 | parent: StringPublicKey; 176 | /// Starting at 0 for master record, this is incremented for each edition minted. 177 | edition: BN; 178 | 179 | constructor(args: { 180 | key: MetadataKey; 181 | parent: StringPublicKey; 182 | edition: BN; 183 | }) { 184 | this.key = MetadataKey.EditionV1; 185 | this.parent = args.parent; 186 | this.edition = args.edition; 187 | } 188 | } 189 | export class Creator { 190 | address: StringPublicKey; 191 | verified: boolean; 192 | share: number; 193 | 194 | constructor(args: { 195 | address: StringPublicKey; 196 | verified: boolean; 197 | share: number; 198 | }) { 199 | this.address = args.address; 200 | this.verified = args.verified; 201 | this.share = args.share; 202 | } 203 | } 204 | 205 | export class Data { 206 | name: string; 207 | symbol: string; 208 | uri: string; 209 | sellerFeeBasisPoints: number; 210 | creators: Creator[] | null; 211 | constructor(args: { 212 | name: string; 213 | symbol: string; 214 | uri: string; 215 | sellerFeeBasisPoints: number; 216 | creators: Creator[] | null; 217 | }) { 218 | this.name = args.name; 219 | this.symbol = args.symbol; 220 | this.uri = args.uri; 221 | this.sellerFeeBasisPoints = args.sellerFeeBasisPoints; 222 | this.creators = args.creators; 223 | } 224 | } 225 | 226 | export class Metadata { 227 | key: MetadataKey; 228 | updateAuthority: StringPublicKey; 229 | mint: StringPublicKey; 230 | data: Data; 231 | primarySaleHappened: boolean; 232 | isMutable: boolean; 233 | editionNonce: number | null; 234 | 235 | // set lazy 236 | masterEdition?: StringPublicKey; 237 | edition?: StringPublicKey; 238 | 239 | constructor(args: { 240 | updateAuthority: StringPublicKey; 241 | mint: StringPublicKey; 242 | data: Data; 243 | primarySaleHappened: boolean; 244 | isMutable: boolean; 245 | editionNonce: number | null; 246 | }) { 247 | this.key = MetadataKey.MetadataV1; 248 | this.updateAuthority = args.updateAuthority; 249 | this.mint = args.mint; 250 | this.data = args.data; 251 | this.primarySaleHappened = args.primarySaleHappened; 252 | this.isMutable = args.isMutable; 253 | this.editionNonce = args.editionNonce ?? null; 254 | } 255 | 256 | public async init() { 257 | const metadata = toPublicKey(programIds().metadata); 258 | /* 259 | This nonce stuff doesnt work - we are doing something wrong here. TODO fix. 260 | if (this.editionNonce !== null) { 261 | this.edition = ( 262 | await PublicKey.createProgramAddress( 263 | [ 264 | Buffer.from(METADATA_PREFIX), 265 | metadata.toBuffer(), 266 | toPublicKey(this.mint).toBuffer(), 267 | new Uint8Array([this.editionNonce || 0]), 268 | ], 269 | metadata, 270 | ) 271 | ).toBase58(); 272 | } else {*/ 273 | this.edition = await getEdition(this.mint); 274 | //} 275 | this.masterEdition = this.edition; 276 | } 277 | } 278 | 279 | class CreateMetadataArgs { 280 | instruction: number = 0; 281 | data: Data; 282 | isMutable: boolean; 283 | 284 | constructor(args: { data: Data; isMutable: boolean }) { 285 | this.data = args.data; 286 | this.isMutable = args.isMutable; 287 | } 288 | } 289 | class UpdateMetadataArgs { 290 | instruction: number = 1; 291 | data: Data | null; 292 | // Not used by this app, just required for instruction 293 | updateAuthority: StringPublicKey | null; 294 | primarySaleHappened: boolean | null; 295 | constructor(args: { 296 | data?: Data; 297 | updateAuthority?: string; 298 | primarySaleHappened: boolean | null; 299 | }) { 300 | this.data = args.data ? args.data : null; 301 | this.updateAuthority = args.updateAuthority ? args.updateAuthority : null; 302 | this.primarySaleHappened = args.primarySaleHappened; 303 | } 304 | } 305 | 306 | class CreateMasterEditionArgs { 307 | instruction: number = 10; 308 | maxSupply: BN | null; 309 | constructor(args: { maxSupply: BN | null }) { 310 | this.maxSupply = args.maxSupply; 311 | } 312 | } 313 | 314 | class MintPrintingTokensArgs { 315 | instruction: number = 9; 316 | supply: BN; 317 | 318 | constructor(args: { supply: BN }) { 319 | this.supply = args.supply; 320 | } 321 | } 322 | 323 | export const METADATA_SCHEMA = new Map([ 324 | [ 325 | CreateMetadataArgs, 326 | { 327 | kind: 'struct', 328 | fields: [ 329 | ['instruction', 'u8'], 330 | ['data', Data], 331 | ['isMutable', 'u8'], // bool 332 | ], 333 | }, 334 | ], 335 | [ 336 | UpdateMetadataArgs, 337 | { 338 | kind: 'struct', 339 | fields: [ 340 | ['instruction', 'u8'], 341 | ['data', { kind: 'option', type: Data }], 342 | ['updateAuthority', { kind: 'option', type: 'pubkeyAsString' }], 343 | ['primarySaleHappened', { kind: 'option', type: 'u8' }], 344 | ], 345 | }, 346 | ], 347 | 348 | [ 349 | CreateMasterEditionArgs, 350 | { 351 | kind: 'struct', 352 | fields: [ 353 | ['instruction', 'u8'], 354 | ['maxSupply', { kind: 'option', type: 'u64' }], 355 | ], 356 | }, 357 | ], 358 | [ 359 | MintPrintingTokensArgs, 360 | { 361 | kind: 'struct', 362 | fields: [ 363 | ['instruction', 'u8'], 364 | ['supply', 'u64'], 365 | ], 366 | }, 367 | ], 368 | [ 369 | MasterEditionV1, 370 | { 371 | kind: 'struct', 372 | fields: [ 373 | ['key', 'u8'], 374 | ['supply', 'u64'], 375 | ['maxSupply', { kind: 'option', type: 'u64' }], 376 | ['printingMint', 'pubkeyAsString'], 377 | ['oneTimePrintingAuthorizationMint', 'pubkeyAsString'], 378 | ], 379 | }, 380 | ], 381 | [ 382 | MasterEditionV2, 383 | { 384 | kind: 'struct', 385 | fields: [ 386 | ['key', 'u8'], 387 | ['supply', 'u64'], 388 | ['maxSupply', { kind: 'option', type: 'u64' }], 389 | ], 390 | }, 391 | ], 392 | [ 393 | Edition, 394 | { 395 | kind: 'struct', 396 | fields: [ 397 | ['key', 'u8'], 398 | ['parent', 'pubkeyAsString'], 399 | ['edition', 'u64'], 400 | ], 401 | }, 402 | ], 403 | [ 404 | Data, 405 | { 406 | kind: 'struct', 407 | fields: [ 408 | ['name', 'string'], 409 | ['symbol', 'string'], 410 | ['uri', 'string'], 411 | ['sellerFeeBasisPoints', 'u16'], 412 | ['creators', { kind: 'option', type: [Creator] }], 413 | ], 414 | }, 415 | ], 416 | [ 417 | Creator, 418 | { 419 | kind: 'struct', 420 | fields: [ 421 | ['address', 'pubkeyAsString'], 422 | ['verified', 'u8'], 423 | ['share', 'u8'], 424 | ], 425 | }, 426 | ], 427 | [ 428 | Metadata, 429 | { 430 | kind: 'struct', 431 | fields: [ 432 | ['key', 'u8'], 433 | ['updateAuthority', 'pubkeyAsString'], 434 | ['mint', 'pubkeyAsString'], 435 | ['data', Data], 436 | ['primarySaleHappened', 'u8'], // bool 437 | ['isMutable', 'u8'], // bool 438 | ['editionNonce', { kind: 'option', type: 'u8' }], 439 | ], 440 | }, 441 | ], 442 | [ 443 | EditionMarker, 444 | { 445 | kind: 'struct', 446 | fields: [ 447 | ['key', 'u8'], 448 | ['ledger', [31]], 449 | ], 450 | }, 451 | ], 452 | ]); 453 | 454 | // eslint-disable-next-line no-control-regex 455 | const METADATA_REPLACE = new RegExp('\u0000', 'g'); 456 | 457 | export const decodeMetadata = (buffer: Buffer): Metadata => { 458 | const metadata = deserializeUnchecked( 459 | METADATA_SCHEMA, 460 | Metadata, 461 | buffer, 462 | ) as Metadata; 463 | metadata.data.name = metadata.data.name.replace(METADATA_REPLACE, ''); 464 | metadata.data.uri = metadata.data.uri.replace(METADATA_REPLACE, ''); 465 | metadata.data.symbol = metadata.data.symbol.replace(METADATA_REPLACE, ''); 466 | return metadata; 467 | }; 468 | 469 | export const decodeEditionMarker = (buffer: Buffer): EditionMarker => { 470 | const editionMarker = deserializeUnchecked( 471 | METADATA_SCHEMA, 472 | EditionMarker, 473 | buffer, 474 | ) as EditionMarker; 475 | return editionMarker; 476 | }; 477 | 478 | export const decodeEdition = (buffer: Buffer) => { 479 | return deserializeUnchecked(METADATA_SCHEMA, Edition, buffer) as Edition; 480 | }; 481 | 482 | export const decodeMasterEdition = ( 483 | buffer: Buffer, 484 | ): MasterEditionV1 | MasterEditionV2 => { 485 | if (buffer[0] == MetadataKey.MasterEditionV1) { 486 | return deserializeUnchecked( 487 | METADATA_SCHEMA, 488 | MasterEditionV1, 489 | buffer, 490 | ) as MasterEditionV1; 491 | } else { 492 | return deserializeUnchecked( 493 | METADATA_SCHEMA, 494 | MasterEditionV2, 495 | buffer, 496 | ) as MasterEditionV2; 497 | } 498 | }; 499 | 500 | export async function updateMetadata( 501 | data: Data | undefined, 502 | newUpdateAuthority: string | undefined, 503 | primarySaleHappened: boolean | null | undefined, 504 | mintKey: StringPublicKey, 505 | updateAuthority: StringPublicKey, 506 | instructions: TransactionInstruction[], 507 | metadataAccount?: StringPublicKey, 508 | ) { 509 | const metadataProgramId = programIds().metadata; 510 | 511 | metadataAccount = 512 | metadataAccount || 513 | ( 514 | await findProgramAddress( 515 | [ 516 | Buffer.from('metadata'), 517 | toPublicKey(metadataProgramId).toBuffer(), 518 | toPublicKey(mintKey).toBuffer(), 519 | ], 520 | toPublicKey(metadataProgramId), 521 | ) 522 | )[0]; 523 | 524 | const value = new UpdateMetadataArgs({ 525 | data, 526 | updateAuthority: !newUpdateAuthority ? undefined : newUpdateAuthority, 527 | primarySaleHappened: 528 | primarySaleHappened === null || primarySaleHappened === undefined 529 | ? null 530 | : primarySaleHappened, 531 | }); 532 | const txnData = Buffer.from(serialize(METADATA_SCHEMA, value)); 533 | const keys = [ 534 | { 535 | pubkey: toPublicKey(metadataAccount), 536 | isSigner: false, 537 | isWritable: true, 538 | }, 539 | { 540 | pubkey: toPublicKey(updateAuthority), 541 | isSigner: true, 542 | isWritable: false, 543 | }, 544 | ]; 545 | instructions.push( 546 | new TransactionInstruction({ 547 | keys, 548 | programId: toPublicKey(metadataProgramId), 549 | data: txnData, 550 | }), 551 | ); 552 | 553 | return metadataAccount; 554 | } 555 | 556 | export async function createMetadata( 557 | data: Data, 558 | updateAuthority: StringPublicKey, 559 | mintKey: StringPublicKey, 560 | mintAuthorityKey: StringPublicKey, 561 | instructions: TransactionInstruction[], 562 | payer: StringPublicKey, 563 | ) { 564 | const metadataProgramId = programIds().metadata; 565 | 566 | const metadataAccount = ( 567 | await findProgramAddress( 568 | [ 569 | Buffer.from('metadata'), 570 | toPublicKey(metadataProgramId).toBuffer(), 571 | toPublicKey(mintKey).toBuffer(), 572 | ], 573 | toPublicKey(metadataProgramId), 574 | ) 575 | )[0]; 576 | const value = new CreateMetadataArgs({ data, isMutable: true }); 577 | const txnData = Buffer.from(serialize(METADATA_SCHEMA, value)); 578 | 579 | const keys = [ 580 | { 581 | pubkey: toPublicKey(metadataAccount), 582 | isSigner: false, 583 | isWritable: true, 584 | }, 585 | { 586 | pubkey: toPublicKey(mintKey), 587 | isSigner: false, 588 | isWritable: false, 589 | }, 590 | { 591 | pubkey: toPublicKey(mintAuthorityKey), 592 | isSigner: true, 593 | isWritable: false, 594 | }, 595 | { 596 | pubkey: toPublicKey(payer), 597 | isSigner: true, 598 | isWritable: false, 599 | }, 600 | { 601 | pubkey: toPublicKey(updateAuthority), 602 | isSigner: false, 603 | isWritable: false, 604 | }, 605 | { 606 | pubkey: SystemProgram.programId, 607 | isSigner: false, 608 | isWritable: false, 609 | }, 610 | { 611 | pubkey: SYSVAR_RENT_PUBKEY, 612 | isSigner: false, 613 | isWritable: false, 614 | }, 615 | ]; 616 | instructions.push( 617 | new TransactionInstruction({ 618 | keys, 619 | programId: toPublicKey(metadataProgramId), 620 | data: txnData, 621 | }), 622 | ); 623 | 624 | return metadataAccount; 625 | } 626 | 627 | export async function createMasterEdition( 628 | maxSupply: BN | undefined, 629 | mintKey: StringPublicKey, 630 | updateAuthorityKey: StringPublicKey, 631 | mintAuthorityKey: StringPublicKey, 632 | payer: StringPublicKey, 633 | instructions: TransactionInstruction[], 634 | ) { 635 | const metadataProgramId = programIds().metadata; 636 | 637 | const metadataAccount = ( 638 | await findProgramAddress( 639 | [ 640 | Buffer.from(METADATA_PREFIX), 641 | toPublicKey(metadataProgramId).toBuffer(), 642 | toPublicKey(mintKey).toBuffer(), 643 | ], 644 | toPublicKey(metadataProgramId), 645 | ) 646 | )[0]; 647 | 648 | const editionAccount = ( 649 | await findProgramAddress( 650 | [ 651 | Buffer.from(METADATA_PREFIX), 652 | toPublicKey(metadataProgramId).toBuffer(), 653 | toPublicKey(mintKey).toBuffer(), 654 | Buffer.from(EDITION), 655 | ], 656 | toPublicKey(metadataProgramId), 657 | ) 658 | )[0]; 659 | 660 | const value = new CreateMasterEditionArgs({ maxSupply: maxSupply || null }); 661 | const data = Buffer.from(serialize(METADATA_SCHEMA, value)); 662 | 663 | const keys = [ 664 | { 665 | pubkey: toPublicKey(editionAccount), 666 | isSigner: false, 667 | isWritable: true, 668 | }, 669 | { 670 | pubkey: toPublicKey(mintKey), 671 | isSigner: false, 672 | isWritable: true, 673 | }, 674 | { 675 | pubkey: toPublicKey(updateAuthorityKey), 676 | isSigner: true, 677 | isWritable: false, 678 | }, 679 | { 680 | pubkey: toPublicKey(mintAuthorityKey), 681 | isSigner: true, 682 | isWritable: false, 683 | }, 684 | { 685 | pubkey: toPublicKey(payer), 686 | isSigner: true, 687 | isWritable: false, 688 | }, 689 | { 690 | pubkey: toPublicKey(metadataAccount), 691 | isSigner: false, 692 | isWritable: false, 693 | }, 694 | 695 | { 696 | pubkey: programIds().token, 697 | isSigner: false, 698 | isWritable: false, 699 | }, 700 | { 701 | pubkey: SystemProgram.programId, 702 | isSigner: false, 703 | isWritable: false, 704 | }, 705 | { 706 | pubkey: SYSVAR_RENT_PUBKEY, 707 | isSigner: false, 708 | isWritable: false, 709 | }, 710 | ]; 711 | 712 | instructions.push( 713 | new TransactionInstruction({ 714 | keys, 715 | programId: toPublicKey(metadataProgramId), 716 | data, 717 | }), 718 | ); 719 | } 720 | 721 | export async function deprecatedMintNewEditionFromMasterEditionViaPrintingToken( 722 | newMint: StringPublicKey, 723 | tokenMint: StringPublicKey, 724 | newMintAuthority: StringPublicKey, 725 | printingMint: StringPublicKey, 726 | authorizationTokenHoldingAccount: StringPublicKey, 727 | burnAuthority: StringPublicKey, 728 | updateAuthorityOfMaster: StringPublicKey, 729 | reservationList: StringPublicKey | undefined, 730 | instructions: TransactionInstruction[], 731 | payer: StringPublicKey, 732 | ) { 733 | const metadataProgramId = programIds().metadata; 734 | 735 | const newMetadataKey = await getMetadata(newMint); 736 | const masterMetadataKey = await getMetadata(tokenMint); 737 | const newEdition = await getEdition(newMint); 738 | const masterEdition = await getEdition(tokenMint); 739 | 740 | const data = Buffer.from([3]); 741 | 742 | const keys = [ 743 | { 744 | pubkey: toPublicKey(newMetadataKey), 745 | isSigner: false, 746 | isWritable: true, 747 | }, 748 | { 749 | pubkey: toPublicKey(newEdition), 750 | isSigner: false, 751 | isWritable: true, 752 | }, 753 | { 754 | pubkey: toPublicKey(masterEdition), 755 | isSigner: false, 756 | isWritable: true, 757 | }, 758 | { 759 | pubkey: toPublicKey(newMint), 760 | isSigner: false, 761 | isWritable: true, 762 | }, 763 | { 764 | pubkey: toPublicKey(newMintAuthority), 765 | isSigner: true, 766 | isWritable: false, 767 | }, 768 | { 769 | pubkey: toPublicKey(printingMint), 770 | isSigner: false, 771 | isWritable: true, 772 | }, 773 | { 774 | pubkey: toPublicKey(authorizationTokenHoldingAccount), 775 | isSigner: false, 776 | isWritable: true, 777 | }, 778 | { 779 | pubkey: toPublicKey(burnAuthority), 780 | isSigner: true, 781 | isWritable: false, 782 | }, 783 | { 784 | pubkey: toPublicKey(payer), 785 | isSigner: true, 786 | isWritable: false, 787 | }, 788 | { 789 | pubkey: toPublicKey(updateAuthorityOfMaster), 790 | isSigner: false, 791 | isWritable: false, 792 | }, 793 | { 794 | pubkey: toPublicKey(masterMetadataKey), 795 | isSigner: false, 796 | isWritable: false, 797 | }, 798 | { 799 | pubkey: programIds().token, 800 | isSigner: false, 801 | isWritable: false, 802 | }, 803 | { 804 | pubkey: SystemProgram.programId, 805 | isSigner: false, 806 | isWritable: false, 807 | }, 808 | { 809 | pubkey: SYSVAR_RENT_PUBKEY, 810 | isSigner: false, 811 | isWritable: false, 812 | }, 813 | ]; 814 | 815 | if (reservationList) { 816 | keys.push({ 817 | pubkey: toPublicKey(reservationList), 818 | isSigner: false, 819 | isWritable: true, 820 | }); 821 | } 822 | instructions.push( 823 | new TransactionInstruction({ 824 | keys, 825 | programId: toPublicKey(metadataProgramId), 826 | data, 827 | }), 828 | ); 829 | } 830 | 831 | export async function mintNewEditionFromMasterEditionViaToken( 832 | newMint: StringPublicKey, 833 | tokenMint: StringPublicKey, 834 | newMintAuthority: StringPublicKey, 835 | newUpdateAuthority: StringPublicKey, 836 | tokenOwner: StringPublicKey, 837 | tokenAccount: StringPublicKey, 838 | instructions: TransactionInstruction[], 839 | payer: StringPublicKey, 840 | edition: BN, 841 | ) { 842 | const metadataProgramId = programIds().metadata; 843 | 844 | const newMetadataKey = await getMetadata(newMint); 845 | const masterMetadataKey = await getMetadata(tokenMint); 846 | const newEdition = await getEdition(newMint); 847 | const masterEdition = await getEdition(tokenMint); 848 | const editionMarkPda = await getEditionMarkPda(tokenMint, edition); 849 | 850 | const data = Buffer.from([11, ...edition.toArray('le', 8)]); 851 | 852 | const keys = [ 853 | { 854 | pubkey: toPublicKey(newMetadataKey), 855 | isSigner: false, 856 | isWritable: true, 857 | }, 858 | { 859 | pubkey: toPublicKey(newEdition), 860 | isSigner: false, 861 | isWritable: true, 862 | }, 863 | { 864 | pubkey: toPublicKey(masterEdition), 865 | isSigner: false, 866 | isWritable: true, 867 | }, 868 | { 869 | pubkey: toPublicKey(newMint), 870 | isSigner: false, 871 | isWritable: true, 872 | }, 873 | { 874 | pubkey: toPublicKey(editionMarkPda), 875 | isSigner: false, 876 | isWritable: true, 877 | }, 878 | { 879 | pubkey: toPublicKey(newMintAuthority), 880 | isSigner: true, 881 | isWritable: false, 882 | }, 883 | { 884 | pubkey: toPublicKey(payer), 885 | isSigner: true, 886 | isWritable: false, 887 | }, 888 | { 889 | pubkey: toPublicKey(tokenOwner), 890 | isSigner: true, 891 | isWritable: false, 892 | }, 893 | { 894 | pubkey: toPublicKey(tokenAccount), 895 | isSigner: false, 896 | isWritable: false, 897 | }, 898 | { 899 | pubkey: toPublicKey(newUpdateAuthority), 900 | isSigner: false, 901 | isWritable: false, 902 | }, 903 | { 904 | pubkey: toPublicKey(masterMetadataKey), 905 | isSigner: false, 906 | isWritable: false, 907 | }, 908 | { 909 | pubkey: programIds().token, 910 | isSigner: false, 911 | isWritable: false, 912 | }, 913 | { 914 | pubkey: SystemProgram.programId, 915 | isSigner: false, 916 | isWritable: false, 917 | }, 918 | { 919 | pubkey: SYSVAR_RENT_PUBKEY, 920 | isSigner: false, 921 | isWritable: false, 922 | }, 923 | ]; 924 | 925 | instructions.push( 926 | new TransactionInstruction({ 927 | keys, 928 | programId: toPublicKey(metadataProgramId), 929 | data, 930 | }), 931 | ); 932 | } 933 | 934 | export async function updatePrimarySaleHappenedViaToken( 935 | metadata: StringPublicKey, 936 | owner: StringPublicKey, 937 | tokenAccount: StringPublicKey, 938 | instructions: TransactionInstruction[], 939 | ) { 940 | const metadataProgramId = programIds().metadata; 941 | 942 | const data = Buffer.from([4]); 943 | 944 | const keys = [ 945 | { 946 | pubkey: toPublicKey(metadata), 947 | isSigner: false, 948 | isWritable: true, 949 | }, 950 | { 951 | pubkey: toPublicKey(owner), 952 | isSigner: true, 953 | isWritable: false, 954 | }, 955 | { 956 | pubkey: toPublicKey(tokenAccount), 957 | isSigner: false, 958 | isWritable: false, 959 | }, 960 | ]; 961 | instructions.push( 962 | new TransactionInstruction({ 963 | keys, 964 | programId: toPublicKey(metadataProgramId), 965 | data, 966 | }), 967 | ); 968 | } 969 | 970 | export async function deprecatedCreateReservationList( 971 | metadata: StringPublicKey, 972 | masterEdition: StringPublicKey, 973 | resource: StringPublicKey, 974 | updateAuthority: StringPublicKey, 975 | payer: StringPublicKey, 976 | instructions: TransactionInstruction[], 977 | ) { 978 | const metadataProgramId = programIds().metadata; 979 | 980 | const reservationList = await deprecatedGetReservationList( 981 | masterEdition, 982 | resource, 983 | ); 984 | const data = Buffer.from([6]); 985 | 986 | const keys = [ 987 | { 988 | pubkey: toPublicKey(reservationList), 989 | isSigner: false, 990 | isWritable: true, 991 | }, 992 | { 993 | pubkey: toPublicKey(payer), 994 | isSigner: true, 995 | isWritable: false, 996 | }, 997 | { 998 | pubkey: toPublicKey(updateAuthority), 999 | isSigner: true, 1000 | isWritable: false, 1001 | }, 1002 | 1003 | { 1004 | pubkey: toPublicKey(masterEdition), 1005 | isSigner: false, 1006 | isWritable: false, 1007 | }, 1008 | { 1009 | pubkey: toPublicKey(resource), 1010 | isSigner: false, 1011 | isWritable: false, 1012 | }, 1013 | { 1014 | pubkey: toPublicKey(metadata), 1015 | isSigner: false, 1016 | isWritable: false, 1017 | }, 1018 | { 1019 | pubkey: SystemProgram.programId, 1020 | isSigner: false, 1021 | isWritable: false, 1022 | }, 1023 | { 1024 | pubkey: SYSVAR_RENT_PUBKEY, 1025 | isSigner: false, 1026 | isWritable: false, 1027 | }, 1028 | ]; 1029 | instructions.push( 1030 | new TransactionInstruction({ 1031 | keys, 1032 | programId: toPublicKey(metadataProgramId), 1033 | data, 1034 | }), 1035 | ); 1036 | } 1037 | 1038 | export async function signMetadata( 1039 | metadata: StringPublicKey, 1040 | creator: StringPublicKey, 1041 | instructions: TransactionInstruction[], 1042 | ) { 1043 | const metadataProgramId = programIds().metadata; 1044 | 1045 | const data = Buffer.from([7]); 1046 | 1047 | const keys = [ 1048 | { 1049 | pubkey: toPublicKey(metadata), 1050 | isSigner: false, 1051 | isWritable: true, 1052 | }, 1053 | { 1054 | pubkey: toPublicKey(creator), 1055 | isSigner: true, 1056 | isWritable: false, 1057 | }, 1058 | ]; 1059 | instructions.push( 1060 | new TransactionInstruction({ 1061 | keys, 1062 | programId: toPublicKey(metadataProgramId), 1063 | data, 1064 | }), 1065 | ); 1066 | } 1067 | 1068 | export async function deprecatedMintPrintingTokens( 1069 | destination: StringPublicKey, 1070 | printingMint: StringPublicKey, 1071 | updateAuthority: StringPublicKey, 1072 | metadata: StringPublicKey, 1073 | masterEdition: StringPublicKey, 1074 | supply: BN, 1075 | instructions: TransactionInstruction[], 1076 | ) { 1077 | const PROGRAM_IDS = programIds(); 1078 | const metadataProgramId = PROGRAM_IDS.metadata; 1079 | 1080 | const value = new MintPrintingTokensArgs({ supply }); 1081 | const data = Buffer.from(serialize(METADATA_SCHEMA, value)); 1082 | 1083 | const keys = [ 1084 | { 1085 | pubkey: toPublicKey(destination), 1086 | isSigner: false, 1087 | isWritable: true, 1088 | }, 1089 | { 1090 | pubkey: toPublicKey(printingMint), 1091 | isSigner: false, 1092 | isWritable: true, 1093 | }, 1094 | { 1095 | pubkey: toPublicKey(updateAuthority), 1096 | isSigner: true, 1097 | isWritable: false, 1098 | }, 1099 | { 1100 | pubkey: toPublicKey(metadata), 1101 | isSigner: false, 1102 | isWritable: false, 1103 | }, 1104 | { 1105 | pubkey: toPublicKey(masterEdition), 1106 | isSigner: false, 1107 | isWritable: false, 1108 | }, 1109 | { 1110 | pubkey: PROGRAM_IDS.token, 1111 | isSigner: false, 1112 | isWritable: false, 1113 | }, 1114 | { 1115 | pubkey: SYSVAR_RENT_PUBKEY, 1116 | isSigner: false, 1117 | isWritable: false, 1118 | }, 1119 | ]; 1120 | instructions.push( 1121 | new TransactionInstruction({ 1122 | keys, 1123 | programId: toPublicKey(metadataProgramId), 1124 | data, 1125 | }), 1126 | ); 1127 | } 1128 | 1129 | export async function convertMasterEditionV1ToV2( 1130 | masterEdition: StringPublicKey, 1131 | oneTimeAuthMint: StringPublicKey, 1132 | printingMint: StringPublicKey, 1133 | instructions: TransactionInstruction[], 1134 | ) { 1135 | const metadataProgramId = programIds().metadata; 1136 | 1137 | const data = Buffer.from([12]); 1138 | 1139 | const keys = [ 1140 | { 1141 | pubkey: toPublicKey(masterEdition), 1142 | isSigner: false, 1143 | isWritable: true, 1144 | }, 1145 | { 1146 | pubkey: toPublicKey(oneTimeAuthMint), 1147 | isSigner: false, 1148 | isWritable: true, 1149 | }, 1150 | { 1151 | pubkey: toPublicKey(printingMint), 1152 | isSigner: false, 1153 | isWritable: true, 1154 | }, 1155 | ]; 1156 | instructions.push( 1157 | new TransactionInstruction({ 1158 | keys, 1159 | programId: toPublicKey(metadataProgramId), 1160 | data, 1161 | }), 1162 | ); 1163 | } 1164 | 1165 | export async function getEdition( 1166 | tokenMint: StringPublicKey, 1167 | ): Promise { 1168 | const PROGRAM_IDS = programIds(); 1169 | 1170 | return ( 1171 | await findProgramAddress( 1172 | [ 1173 | Buffer.from(METADATA_PREFIX), 1174 | toPublicKey(PROGRAM_IDS.metadata).toBuffer(), 1175 | toPublicKey(tokenMint).toBuffer(), 1176 | Buffer.from(EDITION), 1177 | ], 1178 | toPublicKey(PROGRAM_IDS.metadata), 1179 | ) 1180 | )[0]; 1181 | } 1182 | 1183 | export async function getMetadata( 1184 | tokenMint: StringPublicKey, 1185 | ): Promise { 1186 | const PROGRAM_IDS = programIds(); 1187 | 1188 | return ( 1189 | await findProgramAddress( 1190 | [ 1191 | Buffer.from(METADATA_PREFIX), 1192 | toPublicKey(PROGRAM_IDS.metadata).toBuffer(), 1193 | toPublicKey(tokenMint).toBuffer(), 1194 | ], 1195 | toPublicKey(PROGRAM_IDS.metadata), 1196 | ) 1197 | )[0]; 1198 | } 1199 | 1200 | export async function deprecatedGetReservationList( 1201 | masterEdition: StringPublicKey, 1202 | resource: StringPublicKey, 1203 | ): Promise { 1204 | const PROGRAM_IDS = programIds(); 1205 | 1206 | return ( 1207 | await findProgramAddress( 1208 | [ 1209 | Buffer.from(METADATA_PREFIX), 1210 | toPublicKey(PROGRAM_IDS.metadata).toBuffer(), 1211 | toPublicKey(masterEdition).toBuffer(), 1212 | Buffer.from(RESERVATION), 1213 | toPublicKey(resource).toBuffer(), 1214 | ], 1215 | toPublicKey(PROGRAM_IDS.metadata), 1216 | ) 1217 | )[0]; 1218 | } 1219 | 1220 | export async function getEditionMarkPda( 1221 | mint: StringPublicKey, 1222 | edition: BN, 1223 | ): Promise { 1224 | const PROGRAM_IDS = programIds(); 1225 | const editionNumber = Math.floor(edition.toNumber() / 248); 1226 | 1227 | return ( 1228 | await findProgramAddress( 1229 | [ 1230 | Buffer.from(METADATA_PREFIX), 1231 | toPublicKey(PROGRAM_IDS.metadata).toBuffer(), 1232 | toPublicKey(mint).toBuffer(), 1233 | Buffer.from(EDITION), 1234 | Buffer.from(editionNumber.toString()), 1235 | ], 1236 | toPublicKey(PROGRAM_IDS.metadata), 1237 | ) 1238 | )[0]; 1239 | } 1240 | --------------------------------------------------------------------------------