Skip to content

Commit

Permalink
Initialize wallet integration with starknetkit
Browse files Browse the repository at this point in the history
  • Loading branch information
b-j-roberts committed Dec 18, 2024
1 parent 3a90238 commit a2219d3
Show file tree
Hide file tree
Showing 15 changed files with 2,419 additions and 66 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Needed to run Indexer
APIBARA_AUTH_TOKEN=dna_xxx

# Only needed to deploy the contract
STARKNET_KEYSTORE=$HOME/.starkli-sepolia/starkli-keystore.json
STARKNET_ACCOUNT=$HOME/.starkli-sepolia/starkli-account.json
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ broly/
├── packages/
│ ├── inscribor/ # Bitcoin inscription service
│ ├── onchain/ # Starknet smart contracts
│ ├── scripts/ # Deployment & Testing scripts
│ └── indexer/ # Starknet contract indexing
├── package.json
└── turbo.json
Expand Down
4 changes: 3 additions & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router": "^7.0.1"
"react-router": "^7.0.1",
"starknet": "^6.11.0",
"starknetkit": "^2.6.1"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
Expand Down
155 changes: 149 additions & 6 deletions apps/web/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { useState } from 'react'
import { useState, useEffect } from 'react'
import { Routes, Route } from 'react-router'
import { connect, disconnect } from "starknetkit";
import { CallData, Contract, RpcProvider, constants, byteArray } from 'starknet';
import './App.css'
import Header from './components/Header'
import orderbook_abi from './abi/orderbook.abi.json';

import Home from './pages/Home'
import Inscriptions from './pages/Inscriptions'
Expand All @@ -10,25 +13,165 @@ import Info from './pages/Info'
import Inscription from './pages/Inscription'
import Request from './pages/Request'

export const NODE_URL = 'https://starknet-sepolia.public.blastapi.io/rpc/v0_7';
export const STARKNET_CHAIN_ID = constants.StarknetChainId.SN_SEPOLIA;

//export const provider = new RpcProvider([NODE_URL], STARKNET_CHAIN_ID);
export const provider = new RpcProvider({
nodeUrl: NODE_URL,
chainId: STARKNET_CHAIN_ID
});

function App() {
// TODO: Move to seperate module ( starknet stuff )
const [starkWallet, setWallet] = useState(null as any)
const [starkConnector, setConnector] = useState(null as any)
const [starkConnectorData, setConnectorData] = useState(null as any)
const [starkAddress, setAddress] = useState(null as any)
const [starkAccount, setStarkAccount] = useState(null as any)

const connectWallet = async () => {
// TODO: If no wallet/connectors?
// TODO: Auto-reconnect on page refresh?
const { wallet, connector, connectorData } = await connect({
modalMode: "alwaysAsk",
modalTheme: "dark"
})
if (!wallet || !connector || !connectorData) {
return
}

setWallet(wallet)
setConnector(connector)
setConnectorData(connectorData)
setAddress(connectorData.account)
let new_account = await connector.account(provider);
setStarkAccount(new_account);
}

const disconnectWallet = async () => {
if (starkConnector) {
await disconnect()
}

setWallet(null)
setConnector(null)
setConnectorData(null)
setAddress(null)
}

const toHex = (str: string) => {
let hex = '0x';
for (let i = 0; i < str.length; i++) {
hex += '' + str.charCodeAt(i).toString(16);
}
return hex;
};

const estimateInvokeFee = async ({
contractAddress,
entrypoint,
calldata
}: {
contractAddress: any;
entrypoint: any;
calldata: any;
}) => {
try {
const { suggestedMaxFee } = await starkAccount.estimateInvokeFee({
contractAddress: contractAddress,
entrypoint: entrypoint,
calldata: calldata
});
return { suggestedMaxFee };
} catch (error) {
console.error(error);
return { suggestedMaxFee: BigInt(1000000000000000) };
}
};

const [orderbookContract, setOrderbookContract] = useState(null as any)
useEffect(() => {
if (!starkConnector || !starkAccount) {
return
}

const newOrderbookContract = new Contract(
orderbook_abi,
import.meta.env.VITE_ORDERBOOK_CONTRACT_ADDRESS,
starkAccount
)

setOrderbookContract(newOrderbookContract)
}, [starkConnector, starkAccount])

const requestInscriptionCall = async () => {
if (!starkAddress || !orderbookContract) {
return
}
const calldata = CallData.compile([
byteArray.byteArrayFromString("message:Hello, Starknet!"),
byteArray.byteArrayFromString("tb1234567890123456789012345678901234567890"),
Number(100),
toHex("STRK"),
Number(2000)
]);
console.log(calldata);
const requestCalldata = orderbookContract.populate(
"request_inscription",
calldata,
//{
// inscription_data: byteArray.byteArrayFromString("message:Hello, Starknet!"),
// receiving_address: toHex("tb1234567890123456789012345678901234567890"),
// satoshi: Number(100),
// currency_fee: toHex("STRK"),
// submitter_fee: Number(2000),
//}
);
const { suggestedMaxFee } = await estimateInvokeFee({
contractAddress: orderbookContract.address,
entrypoint: "request_inscription",
calldata: requestCalldata.calldata
});
/* global BigInt */
const maxFee = (suggestedMaxFee * BigInt(15)) / BigInt(10);
const result = await orderbookContract.request_inscription(
requestCalldata.calldata,
{
maxFee
}
);
console.log(result);
}

const cancelInscriptionCall = async () => {
// TODO
}

const [tabs, _setTabs] = useState([
{ name: 'Home', path: '/', component: Home },
{ name: 'Home', path: '/', component: Home as any },
{ name: 'Inscriptions', path: '/inscriptions', component: Inscriptions },
{ name: 'Collection', path: '/collection', component: Collection },
{ name: 'Info', path: '/info', component: Info },
])
const tabProps = {
requestInscriptionCall,
cancelInscriptionCall,
orderbookContract,
starkAddress
}

// TODO: <Route path="*" element={<NotFound />} />
return (
<div className="h-screen relative">
<Header tabs={tabs} />
<Header tabs={tabs} connectWallet={connectWallet} address={starkAddress} disconnectWallet={disconnectWallet} />
<div className="h-[4.5rem]" />
<Routes>
{tabs.map((tab) => (
<Route key={tab.path} path={tab.path} element={<tab.component />} />
<Route key={tab.path} path={tab.path} element={<tab.component {...tabProps} />} />
))}
<Route path="/inscription/:id" element={<Inscription />} />
<Route path="/request/:id" element={<Request />} />
<Route path="/inscription/:id" element={<Inscription {...tabProps} />} />
<Route path="/request/:id" element={<Request {...tabProps} />} />
</Routes>
</div>
)
Expand Down
Loading

0 comments on commit a2219d3

Please sign in to comment.