Skip to content

Commit

Permalink
Merge pull request #10 from 0xsequence/doc-additions
Browse files Browse the repository at this point in the history
updated some sections and added a few componenents
  • Loading branch information
moskalyk authored Mar 22, 2024
2 parents ae2398c + dfbbfc1 commit a77149a
Show file tree
Hide file tree
Showing 31 changed files with 2,126 additions and 256 deletions.
23 changes: 23 additions & 0 deletions docs/components/CardGrid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const Card = ({ title, description, icon, link }: any) => {
const CardContent = (
<div className="card">
<div className="card-icon">{icon}</div>
<div className="card-content">
<h2 className="card-title">{title}</h2>
<p className="card-description">{description}</p>
</div>
</div>
);

// If you're using client-side routing:
// return <Link to={link}>{CardContent}</Link>;

// For regular links:
return <a href={link} className="card-link">{CardContent}</a>;
};

const CardGrid = ({ children } : any) => {
return <div className="card-grid">{children}</div>;
};

export { Card, CardGrid };
101 changes: 101 additions & 0 deletions docs/components/MintWidget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@

import React, {useEffect, useState} from 'react';

import {sequence} from '0xsequence'
import { SequenceIndexer } from '@0xsequence/indexer'

function MintWidget(props: any) {

sequence.initWallet('AQAAAAAAADi4zbq6FAIlrlW4qD-o_xw0-5A', {defaultNetwork: props.network})

const [isMinting, setIsMinting] = useState(false)
const [isMintedInPresent, setIsMintedInPresent] = useState(false)
const [alreadyMinted, setAlreadyMinted] = useState(false)
const [txHash, setTxHash] = useState<any>(null)

const handleButtonClick = async () => {
try {
const wallet = await sequence.getWallet()
const details = await wallet.connect({app: 'Sequence Docs'})

if(details.connected){
const indexer = new SequenceIndexer(`https://${props.network}-indexer.sequence.app`, 'AQAAAAAAADi4zbq6FAIlrlW4qD-o_xw0-5A')

// try any contract and account address you'd like :)
const contractAddress = '0x58eb15e3b19545b5c01cbd38dac7497ef924b168'
const accountAddress = details.session?.accountAddress

// query Sequence Indexer for all nft balances of the account on Polygon
const nftBalances = await indexer.getTokenBalances({
contractAddress: contractAddress,
accountAddress: accountAddress,
includeMetadata: true
})

setIsMinting(true)
let isMintedBoolean = false

nftBalances.balances.map((token) => {
if(token.tokenID == '0'){
isMintedBoolean = true
setAlreadyMinted(true)
}
})

if(isMintedBoolean){
setIsMintedInPresent(true)
document.getElementById('mint-button')!.style!.background! = '#3e3e3e'
} else {
const url = 'https://docs-collectible.tpin.workers.dev';
const data = {
address: details.session?.accountAddress
};
const res = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
setTxHash(await res.text())
setIsMintedInPresent(true)
document.getElementById('mint-button')!.style!.background! = '#3e3e3e'
}
}
}catch(err){
console.log('user closed the wallet')
}
};

const openWallet = () => {
console.log('opening wallet')
const wallet = sequence.getWallet()
const path = "wallet/collectibles/421614/0x58eB15E3B19545B5c01Cbd38Dac7497ef924B168/0";
wallet.openWallet(path);
}
return (
<div className="widget">
<div className="widget-header">
</div>
<div className="widget-body">

<img className='mint-image' src={'https://media.discordapp.net/attachments/1091126083895693312/1220699875637985360/morganmoskalyk_a_style_of_this_53c1a28d-df6c-4500-bdb9-1f9b6cec5c97.png?ex=660fe459&is=65fd6f59&hm=a7a871f3fe3245149f07b76e96b5aa2a05754add5d305f311e164f050d21f15c&=&format=webp&quality=lossless&width=560&height=560'}/>
<br/>
<div style={{float:'left'}}>
<button className='mint-button' id="mint-button" disabled={isMinting || txHash != null} onClick={handleButtonClick}>{isMinting ? isMintedInPresent ? alreadyMinted ? "already minted ✓" : "minted ✓" : 'minting...' : 'collect'}</button>
{ isMintedInPresent || alreadyMinted ? <button className='mint-button' id="mint-button" onClick={() => openWallet()}>{'open wallet'}</button> : null }
</div>

</div>
<div className="widget-footer">
<br/>
{isMintedInPresent && txHash ? <div className="dashed-box">
<a href={`https://sepolia.arbiscan.io/tx/${txHash}`} target="_blank">{`arbiscan.io: ${txHash.slice(0,8)}`}...</a>
</div> : <p>Create a wallet and mint a free collectible on {props.network.replace('-', ' ')} in seconds</p>}

</div>
</div>
);
}

export default MintWidget;
47 changes: 47 additions & 0 deletions docs/components/TabGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React, { useState } from "react";

// Tab component for each tab heading
const Tab = ({ children, onClick, isActive }: any) => {
return (
<button className={isActive ? 'active' : ''} onClick={onClick}>
{children}
</button>
);
};

// TabPanel component
const TabPanel = ({ children, isActive }: any) => {
return isActive ? <div>{children}</div> : null;
};

// TabGroup component that wraps the Tab and TabPanel components
const TabGroup = ({ children }: any) => {
const [selectedTab, setSelectedTab] = useState(0);
const tabsAndPanels = React.Children.toArray(children);
const tabs = tabsAndPanels.filter((child: any) => child.type === Tab);
const tabPanels = tabsAndPanels.filter((child: any) => child.type === TabPanel);

return (
<div>
<div className="tabs">
{tabs.map((tab: any, index) =>
React.cloneElement(tab, {
key: index,
onClick: () => setSelectedTab(index),
isActive: selectedTab === index,
})
)}
</div>
<div className="tab-panels">
{tabPanels.map((panel: any, index) =>
React.cloneElement(panel, {
key: index,
isActive: selectedTab === index,
})
)}
</div>
</div>
);
};

export { TabGroup, TabPanel, Tab };
50 changes: 50 additions & 0 deletions docs/components/Table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';

const TableColumn = ({ title }: any) => {
return <th>{title}</th>;
};

const TableRow = ({ children, index }: any) => {
const backgroundColor = index % 2 === 0 ? '#3c393f' : '#1e1d1f';
return (
<tr style={{ backgroundColor }}>
{children}
</tr>
);
};

const TableCell = ({ content, imgSrc }: any) => {
return (
<td>
<div className="cell-content">
{imgSrc && <img src={imgSrc} alt="" className="cell-image" />}
<span className="cell-text">{content}</span>
</div>
</td>
);
};

const Table = ({ rows, columns }: any) => {
return (
<table>
<thead>
<tr>
{columns.map((column: any) => {
return <TableColumn title={column} />
})}
</tr>
</thead>
<tbody>
{rows.map((rowData: any, index: any) => (
<TableRow key={index} index={index}>
<TableCell content={rowData.network} imgSrc={rowData.networkImage} />
<TableCell content={rowData.chainHandle} />
<TableCell content={rowData.indexerEndpoint} />
</TableRow>
))}
</tbody>
</table>
);
};

export default Table;
53 changes: 53 additions & 0 deletions docs/components/Video.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, { useEffect, useRef } from 'react';

const Video = (props: any) => {
// Using useRef to get direct references to the DOM elements
const imageRef = useRef<any>(null);
const videoRef = useRef<any>(null);

useEffect(() => {
// Defining the click event handler function
const handleClick = () => {
if (videoRef.current && imageRef.current) {
videoRef.current.style.display = 'block';
imageRef.current.style.display = 'none';
// Modify the video src to start playing
videoRef.current.src += "?autoplay=1";
}
};

// Adding the event listener to the image
const image = imageRef.current;
image.addEventListener('click', handleClick);

// Cleanup function to remove the event listener
return () => {
image.removeEventListener('click', handleClick);
};
}, []); // The empty dependency array ensures this effect runs only once after initial render

return (
<div className="video-container">
<img
ref={imageRef} // Assigning the ref to the image
className="preview-image"
src={props.videoPreviewSrc}
alt="Preview"
/>
<video
ref={videoRef} // Assigning the ref to the video
className="video-frame"
width="560"
height="315"
controls
muted
src={props.videoSrc}
//@ts-ignore
type="video/mp4"
style={{ display: 'none' }} // Initially hiding the video
/>
</div>
);
};

export default Video;
31 changes: 16 additions & 15 deletions docs/pages/solutions/builder/contracts.mdx
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
---
title: Contracts
hide_title: true
slug: /builder/contracts
---
import Video from "../../../components/Video";

# Contracts in Builder

Sequence Builder simplifies smart contract deployment and management with a suite of user-friendly features. Import, deploy, and add contract collaborators to a smart contract in the contracts dashboard and interact directly with your contract.

##### What are my deployment options?

Deployment of contracts with Sequence Builder is simplified through a streamlined process directly within our dashboard. Choose from various contract templates (ERC1155, ERC721, ERC20). The Builder also gives you the option to upload your own custom contracts - saved to your project - and can be deployed directly to a network of your choosing.

##### What contract interactions can I do?

Sequence Builder provides a comprehensive contract dashboard, allowing users to explore and monitor various smart contract activities like transactions, balance, and tokens. Performing read and executing write operations on contracts becomes effortless, making it easy for actions such as minting and collaborations.

## Watch a Contract be deployed with Builder
<div class="video-container">
<img class="preview-image" src="/img/builder/builder_deploy_contracts.png" />
<video class="video-frame" width="560" height="315" controls muted src="/video/builder/03_Contracts.mp4" type="video/mp4" />
</div>

<Video
videoPreviewSrc={"/img/builder/builder_deploy_contracts.png"}
videoSrc={"/video/builder/03_Contracts.mp4"}
/>

## Add Contract Collaborators to Audited Contracts

Once you have a contract selected from one of the templates deployed, you can navigate to the specific contract and select the settings to view Permissions.

![contract settings](/img/builder/builder_contract_specific_settings.png)
Expand All @@ -32,14 +32,15 @@ Once you have the modal open, select the `Permissions` tab and you can `Edit`, o
Then complete the form with the user's address you want to add as a collaborator and select the dropdown to assign a new role.

##### Possible roles
* Admin: Can update roles
* Minter: Can mint tokens
* Mint Admin: Can set minting logic
* Withdraw: Withdraw tokens from the contract
* Metadata Admin: Can update metadata

- Admin: Can update roles
- Minter: Can mint tokens
- Mint Admin: Can set minting logic
- Withdraw: Withdraw tokens from the contract
- Metadata Admin: Can update metadata

![assign role](/img/builder/builder_contract_permissions_dropdown.png)

Finally, complete and sign the transaction to be deployed to the network the contract is deployed on.

![complete transaction](/img/builder/builder_contract_permissions_transaction.png)
![complete transaction](/img/builder/builder_contract_permissions_transaction.png)
24 changes: 11 additions & 13 deletions docs/pages/solutions/builder/gas-tank.mdx
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
---
title: Gas Tank
hide_title: true
slug: /builder/gas-tank
---
import Video from "../../../components/Video";

# Gas Tank in Builder

Sequence wallets are controlled by smart contracts, enabling transaction fees to be abstracted away from users, a concept known in web3 as *gas*. With Sequence Builder's Gas Tank, you have a streamlined process for sponsoring gas for your users.
Sequence wallets are controlled by smart contracts, enabling transaction fees to be abstracted away from users, a concept known in web3 as _gas_. With Sequence Builder's Gas Tank, you have a streamlined process for sponsoring gas for your users.

##### Why would I want to sponsor gas for my game?
Obtaining the crypto needed to cover fees poses a challenge for traditional gamers. Sponsoring gas on their behalf solves this problem.

Obtaining the crypto needed to cover fees poses a challenge for traditional gamers. Sponsoring gas on their behalf solves this problem.

Gas sponsoring in a web3 game provides seamless onboarding by removing gas fees, making transactions efficient and cost-effective for trading virtual assets in various in-game activities. This creates a more enjoyable gaming experience, fostering player loyalty and community engagement.

##### Sponsoring gas with the Gas Tank
Sponsoring gas on contracts is easy, and can be done either by searching and adding a contract or selecting a contract that you have already deployed on a project. Project owners also have control over the contracts they sponsor, allowing them to temporarily disable a sponsor for a specific contract by toggling it off and updating the sponsor settings.

There are a few options to fund sponsored gas, including a credit card checkout that makes paying for gas simple.
Sponsoring gas on contracts is easy, and can be done either by searching and adding a contract or selecting a contract that you have already deployed on a project. Project owners also have control over the contracts they sponsor, allowing them to temporarily disable a sponsor for a specific contract by toggling it off and updating the sponsor settings.

There are a few options to fund sponsored gas, including a credit card checkout that makes paying for gas simple.

## Watch the Gas Tank in action in Builder
<div class="video-container">
<img class="preview-image" src="/img/builder/builder_sponsor_gas.png" />
<video class="video-frame" width="560" height="315" controls muted src="/video/builder/05_Gas_Tank.mp4" type="video/mp4" />
</div>

<Video
videoPreviewSrc={"/img/builder/builder_sponsor_gas.png"}
videoSrc={"/video/builder/05_Gas_Tank.mp4"}
/>
Loading

0 comments on commit a77149a

Please sign in to comment.