app_store: publish updates and getnameerror

This commit is contained in:
bitful-pannul 2024-07-30 01:38:26 +03:00
parent 62bac1e59f
commit 2e6091e205
4 changed files with 38 additions and 55 deletions

View File

@ -16,6 +16,7 @@ use std::str::FromStr;
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum AppStoreLogError { pub enum AppStoreLogError {
NoBlockNumber, NoBlockNumber,
GetNameError,
DecodeLogError, DecodeLogError,
PackageHashMismatch, PackageHashMismatch,
InvalidPublisherName, InvalidPublisherName,
@ -28,6 +29,7 @@ impl std::fmt::Display for AppStoreLogError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self { match self {
AppStoreLogError::NoBlockNumber => write!(f, "log with no block number"), AppStoreLogError::NoBlockNumber => write!(f, "log with no block number"),
AppStoreLogError::GetNameError => write!(f, "no corresponding name for namehash found"),
AppStoreLogError::DecodeLogError => write!(f, "error decoding log data"), AppStoreLogError::DecodeLogError => write!(f, "error decoding log data"),
AppStoreLogError::PackageHashMismatch => write!(f, "mismatched package hash"), AppStoreLogError::PackageHashMismatch => write!(f, "mismatched package hash"),
AppStoreLogError::InvalidPublisherName => write!(f, "invalid publisher name"), AppStoreLogError::InvalidPublisherName => write!(f, "invalid publisher name"),
@ -371,8 +373,8 @@ impl State {
// use kns_indexer to convert nodehash to a kimap name // use kns_indexer to convert nodehash to a kimap name
let package_full_path = let package_full_path =
net::get_name(&note.nodehash.to_string(), log.block_number, Some(5)) net::get_name(&note.nodehash.to_string(), log.block_number, Some(10))
.ok_or(AppStoreLogError::DecodeLogError)?; .ok_or(AppStoreLogError::GetNameError)?;
// the app store exclusively looks for ~metadata-uri postings: if one is // the app store exclusively looks for ~metadata-uri postings: if one is
// observed, we then *query* for ~metadata-hash to verify the content // observed, we then *query* for ~metadata-hash to verify the content

View File

@ -2,7 +2,7 @@ import { parseAbi } from "viem";
export { encodeMulticalls, encodeIntoMintCall } from "./helpers"; export { encodeMulticalls, encodeIntoMintCall } from "./helpers";
export const KINOMAP: `0x${string}` = "0x0165878A594ca255338adfa4d48449f69242Eb8F"; export const KINOMAP: `0x${string}` = "0x7290Aa297818d0b9660B2871Bb87f85a3f9B4559";
export const MULTICALL: `0x${string}` = "0xcA11bde05977b3631167028862bE2a173976CA11"; export const MULTICALL: `0x${string}` = "0xcA11bde05977b3631167028862bE2a173976CA11";
export const KINO_ACCOUNT_IMPL: `0x${string}` = "0x58790D9957ECE58607A4b58308BBD5FE1a2e4789"; export const KINO_ACCOUNT_IMPL: `0x${string}` = "0x58790D9957ECE58607A4b58308BBD5FE1a2e4789";

View File

@ -10,8 +10,6 @@ import {
import { WagmiProvider, http } from 'wagmi'; import { WagmiProvider, http } from 'wagmi';
import { import {
optimism, optimism,
anvil,
mainnet
} from 'wagmi/chains'; } from 'wagmi/chains';
import { import {
QueryClientProvider, QueryClientProvider,
@ -27,9 +25,7 @@ const config = getDefaultConfig({
chains: [optimism], chains: [optimism],
ssr: false, ssr: false,
transports: { transports: {
[anvil.id]: http(),
[optimism.id]: http(), [optimism.id]: http(),
[mainnet.id]: http(),
} }
}); });

View File

@ -25,7 +25,6 @@ export default function PublishPage() {
const [publisherId, setPublisherId] = useState<string>(window.our?.node || ""); const [publisherId, setPublisherId] = useState<string>(window.our?.node || "");
const [metadataUrl, setMetadataUrl] = useState<string>(""); const [metadataUrl, setMetadataUrl] = useState<string>("");
const [metadataHash, setMetadataHash] = useState<string>(""); const [metadataHash, setMetadataHash] = useState<string>("");
const [isUpdate, setIsUpdate] = useState<boolean>(false);
const [myPublishedApps, setMyPublishedApps] = useState<AppInfo[]>([]); const [myPublishedApps, setMyPublishedApps] = useState<AppInfo[]>([]);
useEffect(() => { useEffect(() => {
@ -33,7 +32,6 @@ export default function PublishPage() {
if (app) { if (app) {
setPackageName(app.package); setPackageName(app.package);
setPublisherId(app.publisher); setPublisherId(app.publisher);
setIsUpdate(true);
} }
}, [state]) }, [state])
@ -65,26 +63,39 @@ export default function PublishPage() {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (!publicClient) { if (!publicClient || !address) {
openConnectModal?.(); openConnectModal?.();
return; return;
} }
let node = window.our?.node || "0x";
let metadata = metadataHash;
if (isUpdate) {
node = `${packageName}.${window.our?.node || "0x"}`;
}
try { try {
// Check if the package already exists and get its TBA
let data = await publicClient.readContract({ let data = await publicClient.readContract({
abi: kinomapAbi, abi: kinomapAbi,
address: KINOMAP, address: KINOMAP,
functionName: 'get', functionName: 'get',
args: [kinohash(node)] args: [kinohash(`${packageName}.${publisherId}`)]
}); });
let [tba, owner, _data] = data as [string, string, string];
let isUpdate = Boolean(tba && tba !== '0x' && owner === address);
let currentTBA = isUpdate ? tba as `0x${string}` : null;
// If the package doesn't exist, check for the publisher's TBA
if (!currentTBA) {
data = await publicClient.readContract({
abi: kinomapAbi,
address: KINOMAP,
functionName: 'get',
args: [kinohash(publisherId)]
});
[tba, owner, _data] = data as [string, string, string];
isUpdate = false; // It's a new package, but we might have a publisher TBA
currentTBA = (tba && tba !== '0x') ? tba as `0x${string}` : null;
}
let metadata = metadataHash;
if (!metadata) { if (!metadata) {
const metadataResponse = await fetch(metadataUrl); const metadataResponse = await fetch(metadataUrl);
await metadataResponse.json(); // confirm it's valid JSON await metadataResponse.json(); // confirm it's valid JSON
@ -93,13 +104,11 @@ export default function PublishPage() {
} }
const multicall = encodeMulticalls(metadataUrl, metadata); const multicall = encodeMulticalls(metadataUrl, metadata);
const args = isUpdate ? multicall : encodeIntoMintCall(multicall, address!, packageName); const args = isUpdate ? multicall : encodeIntoMintCall(multicall, address, packageName);
const [tba, _owner, _data] = data || [];
writeContract({ writeContract({
abi: mechAbi, abi: mechAbi,
address: tba as `0x${string}`, address: currentTBA || KINOMAP,
functionName: 'execute', functionName: 'execute',
args: [ args: [
isUpdate ? MULTICALL : KINOMAP, isUpdate ? MULTICALL : KINOMAP,
@ -115,13 +124,12 @@ export default function PublishPage() {
setPublisherId(window.our?.node || ""); setPublisherId(window.our?.node || "");
setMetadataUrl(""); setMetadataUrl("");
setMetadataHash(""); setMetadataHash("");
setIsUpdate(false);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
}, },
[publicClient, openConnectModal, packageName, publisherId, address, metadataUrl, metadataHash, isUpdate, writeContract] [publicClient, openConnectModal, packageName, publisherId, address, metadataUrl, metadataHash, writeContract]
); );
const unpublishPackage = useCallback( const unpublishPackage = useCallback(
@ -132,17 +140,19 @@ export default function PublishPage() {
return; return;
} }
const node = `${packageName}.${window.our?.node || "0x"}`;
const nodehash = kinohash(node);
const data = await publicClient.readContract({ const data = await publicClient.readContract({
abi: kinomapAbi, abi: kinomapAbi,
address: KINOMAP, address: KINOMAP,
functionName: 'get', functionName: 'get',
args: [nodehash] args: [kinohash(`${packageName}.${publisherName}`)]
}); });
const [tba, _owner, _data] = data || []; const [tba, _owner, _data] = data as [string, string, string];
if (!tba || tba === '0x') {
console.error("No TBA found for this package");
return;
}
const multicall = encodeMulticalls("", ""); const multicall = encodeMulticalls("", "");
@ -165,20 +175,6 @@ export default function PublishPage() {
[publicClient, openConnectModal, writeContract] [publicClient, openConnectModal, writeContract]
); );
const checkIfUpdate = useCallback(() => {
if (isUpdate) return;
if (
packageName &&
publisherId &&
apps.find(
(app) => app.package === packageName && app.publisher === publisherId
)
) {
setIsUpdate(true);
}
}, [apps, packageName, publisherId, isUpdate]);
return ( return (
<div className="publish-page"> <div className="publish-page">
<h1>Publish Package</h1> <h1>Publish Package</h1>
@ -200,15 +196,6 @@ export default function PublishPage() {
<div className="message info">Approve connection in your wallet</div> <div className="message info">Approve connection in your wallet</div>
) : ( ) : (
<form className="publish-form" onSubmit={publishPackage}> <form className="publish-form" onSubmit={publishPackage}>
<div className="form-group">
<input
type="checkbox"
id="update"
checked={isUpdate}
onChange={() => setIsUpdate(!isUpdate)}
/>
<label htmlFor="update">Update existing package</label>
</div>
<div className="form-group"> <div className="form-group">
<label htmlFor="package-name">Package Name</label> <label htmlFor="package-name">Package Name</label>
<input <input
@ -218,7 +205,6 @@ export default function PublishPage() {
placeholder="my-package" placeholder="my-package"
value={packageName} value={packageName}
onChange={(e) => setPackageName(e.target.value)} onChange={(e) => setPackageName(e.target.value)}
onBlur={checkIfUpdate}
/> />
</div> </div>
<div className="form-group"> <div className="form-group">
@ -229,7 +215,6 @@ export default function PublishPage() {
required required
value={publisherId} value={publisherId}
onChange={(e) => setPublisherId(e.target.value)} onChange={(e) => setPublisherId(e.target.value)}
onBlur={checkIfUpdate}
/> />
</div> </div>
<div className="form-group"> <div className="form-group">
@ -265,7 +250,7 @@ export default function PublishPage() {
{isConfirmed && ( {isConfirmed && (
<div className="message success"> <div className="message success">
Package {isUpdate ? 'updated' : 'published'} successfully! Package published successfully!
</div> </div>
)} )}
{error && ( {error && (