Skip to content

Commit

Permalink
feat(react-account): support custom op-sign endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
runjuu committed Nov 1, 2023
1 parent fee2fef commit 3f1e2ac
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 56 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { useRefCallback } from "@crossbell/util-hooks";
import { OP_SIGN_OPERATOR_ADDRESS } from "@crossbell/react-account";
import { useOpSignConfig } from "@crossbell/react-account";

import { TransferCSB as Main } from "../../../../components";

Expand All @@ -15,11 +15,12 @@ export function Transfer() {
const onSuccess = useRefCallback(() => {
goTo({ kind: SceneKind.transferSuccess });
});
const { address } = useOpSignConfig();

return (
<div className={styles.container}>
<Header title="$CSB Transfer" />
<Main toAddress={OP_SIGN_OPERATOR_ADDRESS} onSuccess={onSuccess} />
<Main toAddress={address} onSuccess={onSuccess} />
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { useRefCallback } from "@crossbell/util-hooks";
import { OP_SIGN_OPERATOR_ADDRESS } from "@crossbell/react-account";
import { useOpSignConfig } from "@crossbell/react-account";

import { TransferCSB as Main } from "../../../../components";

Expand All @@ -15,11 +15,12 @@ export function Transfer() {
const onSuccess = useRefCallback(() => {
goTo({ kind: SceneKind.transferSuccess });
});
const { address } = useOpSignConfig();

return (
<div className={styles.container}>
<Header title="$CSB Transfer" />
<Main toAddress={OP_SIGN_OPERATOR_ADDRESS} onSuccess={onSuccess} />
<Main toAddress={address} onSuccess={onSuccess} />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { useRefCallback } from "@crossbell/util-hooks";
import { usePrimaryCharacter } from "@crossbell/indexer";
import {
NEWBIE_VILLA_OPERATOR_ADDRESS,
OP_SIGN_OPERATOR_ADDRESS,
useCharacterOperatorPermissions,
X_SYNC_OPERATOR_ADDRESS,
useCharacterOperatorPermissions,
useOpSignConfig,
} from "@crossbell/react-account";

import commonStyles from "../../../styles.module.css";
Expand Down Expand Up @@ -130,11 +130,12 @@ export function useOperatorAvatar(
const administratorUrl = useWeb2Url(
"ipfs://bafkreib3yzt66fwyeegrinj6ljtjjwpjugcdscepu2iw6kopiaoqsbidtm",
);
const opSign = useOpSignConfig();

if (
isAddressEqual(characterOperator.operator, NEWBIE_VILLA_OPERATOR_ADDRESS) ||
isAddressEqual(characterOperator.operator, X_SYNC_OPERATOR_ADDRESS) ||
isAddressEqual(characterOperator.operator, OP_SIGN_OPERATOR_ADDRESS)
isAddressEqual(characterOperator.operator, opSign.address)
) {
return administratorUrl;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { LoadMore, Loading } from "@crossbell/ui";
import { isAddressEqual } from "viem";
import { CharacterOperatorEntity } from "crossbell";
import {
OP_SIGN_OPERATOR_ADDRESS,
X_SYNC_OPERATOR_ADDRESS,
useGetCharacterOperators,
NEWBIE_VILLA_OPERATOR_ADDRESS,
useGetCharacterOperators,
useOpSignConfig,
type OpSignConfig,
} from "@crossbell/react-account";

import styles from "./list.module.css";
Expand All @@ -21,22 +22,23 @@ export function List({ characterId }: ListProps) {
useGetCharacterOperators({
characterId,
});
const opSignConfig = useOpSignConfig();

const list = React.useMemo(
() =>
data?.pages
.flatMap((page) =>
page.list.map((characterOperator) => ({
characterOperator: characterOperator,
tags: getTags(characterOperator),
description: getDescription(characterOperator),
tags: getTags(characterOperator, { opSignConfig }),
description: getDescription(characterOperator, { opSignConfig }),
})),
)
.filter(
({ characterOperator }) => characterOperator.permissions.length > 0,
)
.sort((a, b) => (a.description ? (b.description ? 0 : -1) : 1)) ?? [],
[data],
[data, opSignConfig],
);

return (
Expand Down Expand Up @@ -68,7 +70,10 @@ export function List({ characterId }: ListProps) {
);
}

function getTags(characterOperator: CharacterOperatorEntity): ItemTag[] | null {
function getTags(
characterOperator: CharacterOperatorEntity,
{ opSignConfig }: { opSignConfig: OpSignConfig },
): ItemTag[] | null {
if (isAddressEqual(characterOperator.operator, X_SYNC_OPERATOR_ADDRESS)) {
return [
{
Expand All @@ -81,7 +86,7 @@ function getTags(characterOperator: CharacterOperatorEntity): ItemTag[] | null {
];
}

if (isAddressEqual(characterOperator.operator, OP_SIGN_OPERATOR_ADDRESS)) {
if (isAddressEqual(characterOperator.operator, opSignConfig.address)) {
return [
{
title: "Op Sign",
Expand Down Expand Up @@ -120,12 +125,13 @@ function getTags(characterOperator: CharacterOperatorEntity): ItemTag[] | null {

function getDescription(
characterOperator: CharacterOperatorEntity,
{ opSignConfig }: { opSignConfig: OpSignConfig },
): string | null {
if (isAddressEqual(characterOperator.operator, X_SYNC_OPERATOR_ADDRESS)) {
return "For syncing other platforms' content";
}

if (isAddressEqual(characterOperator.operator, OP_SIGN_OPERATOR_ADDRESS)) {
if (isAddressEqual(characterOperator.operator, opSignConfig.address)) {
return "For liking, commenting, and minting";
}

Expand Down
84 changes: 58 additions & 26 deletions packages/react-account/src/apis/siwe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import {
NoteEntity,
NoteMetadata,
} from "crossbell";

import { type Address } from "viem";

import { request } from "./utils";
import { BaseSigner } from "../context";
import { getOpSignEndpoint } from "../endpoints-config";

type Siwe = { token: string };

Expand All @@ -19,7 +20,8 @@ export async function siweSignIn(signer: BaseSigner): Promise<Siwe> {
throw new Error(`SignInError: invalid address ${address}`);
}

const { message } = await request<{ message: string }>("/siwe/challenge", {
const { message } = await request<{ message: string }>("/challenge", {
endpoint: getOpSignEndpoint(),
method: "POST",
body: {
address,
Expand All @@ -29,7 +31,8 @@ export async function siweSignIn(signer: BaseSigner): Promise<Siwe> {
},
});

const { token } = await request<{ token: string }>("/siwe/login", {
const { token } = await request<{ token: string }>("/login", {
endpoint: getOpSignEndpoint(),
method: "POST",
body: {
address,
Expand All @@ -41,11 +44,19 @@ export async function siweSignIn(signer: BaseSigner): Promise<Siwe> {
}

export function siweGetAccount(siwe: Siwe): Promise<{ address: Address }> {
return request(`/siwe/account`, { method: "GET", token: siwe.token });
return request(`/account`, {
endpoint: getOpSignEndpoint(),
method: "GET",
token: siwe.token,
});
}

export function siweGetBalance(siwe: Siwe): Promise<{ balance: string }> {
return request(`/siwe/account/balance`, { method: "GET", token: siwe.token });
return request(`/account/balance`, {
endpoint: getOpSignEndpoint(),
method: "GET",
token: siwe.token,
});
}

export async function siweUpdateMetadata({
Expand All @@ -59,7 +70,8 @@ export async function siweUpdateMetadata({
mode?: "merge" | "replace";
metadata: CharacterMetadata;
}): Promise<{ transactionHash: string; data: string }> {
return request(`/siwe/contract/characters/${characterId}/metadata`, {
return request(`/contract/characters/${characterId}/metadata`, {
endpoint: getOpSignEndpoint(),
method: "POST",
token: siwe.token,
body: { metadata, mode },
Expand All @@ -82,8 +94,13 @@ export async function siweLinkNote({
data?: string;
}): Promise<{ transactionHash: string; data: string }> {
return request(
`/siwe/contract/characters/${fromCharacterId}/links/notes/${characterId}/${noteId}/${linkType}`,
{ method: "PUT", token: siwe.token, body: { data } },
`/contract/characters/${fromCharacterId}/links/notes/${characterId}/${noteId}/${linkType}`,
{
endpoint: getOpSignEndpoint(),
method: "PUT",
token: siwe.token,
body: { data },
},
);
}

Expand All @@ -101,8 +118,12 @@ export async function siweUnlinkNote({
linkType: string;
}): Promise<{ transactionHash: string; data: string }> {
return request(
`/siwe/contract/characters/${fromCharacterId}/links/notes/${characterId}/${noteId}/${linkType}`,
{ method: "DELETE", token: siwe.token },
`/contract/characters/${fromCharacterId}/links/notes/${characterId}/${noteId}/${linkType}`,
{
endpoint: getOpSignEndpoint(),
method: "DELETE",
token: siwe.token,
},
);
}

Expand All @@ -120,8 +141,13 @@ export async function siweLinkCharacter({
data?: string;
}): Promise<{ transactionHash: string; data: string }> {
return request(
`/siwe/contract/characters/${characterId}/links/characters/${toCharacterId}/${linkType}`,
{ method: "PUT", token: siwe.token, body: { data } },
`/contract/characters/${characterId}/links/characters/${toCharacterId}/${linkType}`,
{
endpoint: getOpSignEndpoint(),
method: "PUT",
token: siwe.token,
body: { data },
},
);
}

Expand All @@ -140,7 +166,8 @@ export async function siweLinkCharacters({
linkType: string;
data?: string;
}): Promise<{ transactionHash: string; data: string }> {
return request(`/siwe/contract/characters/${characterId}/links/characters`, {
return request(`/contract/characters/${characterId}/links/characters`, {
endpoint: getOpSignEndpoint(),
method: "PUT",
token: siwe.token,
body: { data, linkType, toCharacterIds, toAddresses },
Expand All @@ -159,8 +186,12 @@ export async function siweUnlinkCharacter({
linkType: string;
}): Promise<{ transactionHash: string; data: string }> {
return request(
`/siwe/contract/characters/${characterId}/links/characters/${toCharacterId}/${linkType}`,
{ method: "DELETE", token: siwe.token },
`/contract/characters/${characterId}/links/characters/${toCharacterId}/${linkType}`,
{
endpoint: getOpSignEndpoint(),
method: "DELETE",
token: siwe.token,
},
);
}

Expand All @@ -179,7 +210,8 @@ export async function siwePutNote({
transactionHash: string;
data: { noteId: number };
}> {
return request(`/siwe/contract/characters/${characterId}/notes`, {
return request(`/contract/characters/${characterId}/notes`, {
endpoint: getOpSignEndpoint(),
method: "PUT",
token: siwe.token,
body,
Expand All @@ -198,8 +230,9 @@ export async function siweUpdateNote({
metadata: NoteMetadata;
}): Promise<{ transactionHash: string; data: string }> {
return request(
`/siwe/contract/characters/${characterId}/notes/${noteId}/metadata`,
`/contract/characters/${characterId}/notes/${noteId}/metadata`,
{
endpoint: getOpSignEndpoint(),
method: "POST",
token: siwe.token,
body: { metadata },
Expand All @@ -216,7 +249,8 @@ export async function siweDeleteNote({
characterId: number;
noteId: NoteEntity["noteId"];
}): Promise<{ transactionHash: string; data: string }> {
return request(`/siwe/contract/characters/${characterId}/notes/${noteId}`, {
return request(`/contract/characters/${characterId}/notes/${noteId}`, {
endpoint: getOpSignEndpoint(),
method: "DELETE",
token: siwe.token,
});
Expand All @@ -231,12 +265,10 @@ export function siweMintNote({
characterId: number;
noteId: number;
}) {
return request(
`/siwe/contract/characters/${characterId}/notes/${noteId}/minted`,
{
method: "PUT",
token: siwe.token,
body: {},
},
);
return request(`/contract/characters/${characterId}/notes/${noteId}/minted`, {
endpoint: getOpSignEndpoint(),
method: "PUT",
token: siwe.token,
body: {},
});
}
2 changes: 1 addition & 1 deletion packages/react-account/src/apis/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function request<T = any>(
headers.set("Authorization", `Bearer ${token}`);
}

return fetch((endpoint ?? indexer.endpoint) + url, {
return fetch((endpoint ?? indexer.endpoint).replace(/\/$/g, "") + url, {
method,
headers,
body: body && stringify(body),
Expand Down
20 changes: 20 additions & 0 deletions packages/react-account/src/endpoints-config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { proxy } from "valtio";
import {
opSignConfig,
type OpSignConfig,
} from "./hooks/operator-sign/op-sign-config";

// NewbieVilla

const newbieVillaConfig = proxy({
endpoint: "https://indexer.crossbell.io/v1/newbie",
});
Expand All @@ -12,3 +17,18 @@ export function getNewbieVillaEndpoint() {
export function setNewbieVillaEndpoint(endpoint: string) {
newbieVillaConfig.endpoint = endpoint;
}

// OpSign

export function getOpSignEndpoint() {
return opSignConfig?.endpoint ?? null;
}

export function getOpSignAddress() {
return opSignConfig?.address ?? null;
}

export function setOpSignEndpoint({ endpoint, address }: OpSignConfig) {
opSignConfig.endpoint = endpoint;
opSignConfig.address = address;
}
3 changes: 0 additions & 3 deletions packages/react-account/src/hooks/operator-sign/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,3 @@ export const OP_SIGN_OPERATOR_PERMISSIONS: CharacterPermissionKey[] = [
"POST_NOTE_FOR_ANY_URI",
"POST_NOTE",
];

export const OP_SIGN_OPERATOR_ADDRESS =
"0xbbc2918c9003d264c25ecae45b44a846702c0e7c";
1 change: 1 addition & 0 deletions packages/react-account/src/hooks/operator-sign/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./consts";
export * from "./use-op-sign-config";
export * from "./use-is-op-sign-enabled";
export * from "./use-op-sign-balance";
export * from "./use-toggle-op-sign-operator";
Expand Down
12 changes: 12 additions & 0 deletions packages/react-account/src/hooks/operator-sign/op-sign-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Address } from "viem";
import { proxy } from "valtio";

export type OpSignConfig = {
endpoint: string;
address: Address;
};

export const opSignConfig = proxy<OpSignConfig>({
endpoint: "https://indexer.crossbell.io/v1/siwe/",
address: "0xbbc2918c9003d264c25ecae45b44a846702c0e7c",
});

0 comments on commit 3f1e2ac

Please sign in to comment.