Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Build Tx] Add a Soroban Operation - Extend TTL #1226

Closed
wants to merge 22 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
wip
Jeesun Kim authored and jeesunikim committed Jan 16, 2025
commit 900ec558e591e5ad121131c8673abff28dbe8219
27 changes: 25 additions & 2 deletions src/app/(sidebar)/transaction/build/components/Operations.tsx
Original file line number Diff line number Diff line change
@@ -60,6 +60,7 @@ export const Operations = () => {

const [operationsError, setOperationsError] = useState<OperationError[]>([]);
const [isSaveTxnModalVisible, setIsSaveTxnModalVisible] = useState(false);
const [isSorobanOperation, setIsSorobanOperation] = useState(false);

const INITIAL_OPERATION: TxnOperation = {
operation_type: "",
@@ -218,6 +219,14 @@ export const Operations = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [txnOperations, operationsError, setBuildOperationsError]);

useEffect(() => {
const isSorobanOp = txnOperations.some((op) =>
op.operation_type.includes("restore_footprint"),
);

setIsSorobanOperation(isSorobanOp);
}, [txnOperations]);

const missingSelectedAssetFields = (
param: string,
value: any,
@@ -784,6 +793,13 @@ export const Operations = () => {
return null;
};

const renderSorobanNote = () => (
<Notification variant="warning" title="Only One Operation Allowed">
Note that Soroban transactions can only contain one operation per
transaction.
</Notification>
);

const OperationTypeSelector = ({
index,
operationType,
@@ -886,7 +902,7 @@ export const Operations = () => {
<option value="end_sponsoring_future_reserves">
End Sponsoring Future Reserves
</option>
<option value="restore_footprint">Restore Footprint</option>
<option value="restore_footprint">Restore Footprint (Soroban)</option>
<option value="revoke_sponsorship">Revoke Sponsorship</option>
<option value="clawback">Clawback</option>
<option value="clawback_claimable_balance">
@@ -1176,6 +1192,10 @@ export const Operations = () => {
))}
</>

<Box gap="sm" direction="row" align="center">
{isSorobanOperation ? renderSorobanNote() : null}
</Box>

{/* Operations bottom buttons */}
<Box
gap="lg"
@@ -1188,13 +1208,16 @@ export const Operations = () => {
<Button
size="md"
variant="tertiary"
disabled={true}
disabled={isSorobanOperation}
icon={<Icon.PlusCircle />}
onClick={() => {
// classic operation
updateOptionParamAndError({
type: "add",
item: INITIAL_OPERATION,
});

// todo: soroban operation
}}
>
Add Operation
2 changes: 1 addition & 1 deletion src/components/FormElements/XdrLedgerKeyPicker.tsx
Original file line number Diff line number Diff line change
@@ -82,7 +82,7 @@ const ledgerKeyFields: {
{
id: "contract_data",
label: "Contract Data",
templates: "contract,key,durability",
templates: "contract,storageKey,durability",
},
{
id: "contract_code",
46 changes: 23 additions & 23 deletions src/components/formComponentTemplateEndpoints.tsx
Original file line number Diff line number Diff line change
@@ -264,7 +264,7 @@ export const formComponentTemplateEndpoints = (
<TextPicker
key={id}
id={id}
label="Contract"
label="Contract ID"
placeholder="Ex: CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC"
value={templ.value || ""}
error={templ.error}
@@ -461,33 +461,33 @@ export const formComponentTemplateEndpoints = (
),
validate: null,
};
// contract key
case "key":
// contract data key
case "storageKey":
return {
render: (templ: {
value: string | undefined;
error: string | undefined;
onChange: (val: any) => void;
disabled?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we leave disabled here? There might be cases where we need that.

}) => (
<Textarea
fieldSize="md"
key={id}
id={id}
label="Key"
placeholder="Ex: 67260c4c1807b262ff851b0a3fe141194936bb0215b2f77447f1df11998eabb9"
// @TODO we should display an input for each value
// hotfix: sanitizing value from backlashes and extra quotes
value={
JSON.stringify(templ.value)
.replace(/\\/g, "")
.replace(/^"+|"+$/g, "") || ""
}
error={templ.error}
onChange={templ.onChange}
disabled={templ.disabled}
/>
),
}) => {
return (
<Textarea
fieldSize="md"
key={id}
id={id}
label="Key (Storage Key)"
placeholder='ex: {"string":"Counter"}'
// @TODO we should display an input for each value
// hotfix: sanitizing value from backlashes and extra quotes
value={
JSON.stringify(templ.value)
.replace(/\\/g, "")
.replace(/^"+|"+$/g, "") || ""
}
error={templ.error}
onChange={templ.onChange}
/>
);
},
validate: null,
};
case "ledger":
36 changes: 36 additions & 0 deletions src/components/formComponentTemplateTxnOps.tsx
Original file line number Diff line number Diff line change
@@ -271,6 +271,25 @@ export const formComponentTemplateTxnOps = ({
),
validate: null,
};
case "contract":
return {
render: (templ: {
value: string | undefined;
error: string | undefined;
onChange: (val: any) => void;
}) => (
<TextPicker
key={id}
id={id}
label="Contract ID"
placeholder="Ex: CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC"
value={templ.value || ""}
error={templ.error}
onChange={templ.onChange}
/>
),
validate: validate.getContractIdError,
};
case "data_name":
return {
render: (templ: TemplateRenderProps) => (
@@ -375,6 +394,23 @@ export const formComponentTemplateTxnOps = ({
),
validate: validate.getPublicKeyError,
};
case "key_xdr":
return {
render: (templ: TemplateRenderProps) => (
<TextPicker
key={id}
id={id}
label="(Storage) Key in ScVal XDR Type"
placeholder="Ex: AAAAEAAAAAEAAAACAAAADwAAAAdDb3VudGVyAAAAABIAAAAAAAAAAHkOSeQVxNP4zqcstl6AA+PwtKrnRwrp7+LGt4xqEnTC"
labelSuffix={!templ.isRequired ? "optional" : undefined}
value={templ.value || ""}
error={templ.error}
onChange={templ.onChange}
/>
),
// validate: validate.getXdrError,
validate: validate.getPublicKeyError,
};
case "limit":
return {
render: (templ: TemplateRenderProps) => (
13 changes: 10 additions & 3 deletions src/constants/transactionOperations.tsx
Original file line number Diff line number Diff line change
@@ -338,10 +338,17 @@ export const TRANSACTION_OPERATIONS: { [key: string]: TransactionOperation } = {
"https://developers.stellar.org/docs/learn/fundamentals/transactions/list-of-operations#clawback",
params: ["asset", "from", "amount"],
requiredParams: ["asset", "from", "amount"],
},
restore_footprint: {
label: "Restore Footprint",
description:
"Make archived Soroban smart contract entries accessible again by restoring them.",
docsUrl:
"https://developers.stellar.org/docs/learn/fundamentals/transactions/list-of-operations#restore-footprint",
params: ["contract", "key_xdr"],
requiredParams: ["contract", "key_xdr"],
custom: {
asset: {
includeNative: false,
},
isSorobanTx: true,
},
},
revoke_sponsorship: {
2 changes: 1 addition & 1 deletion src/types/types.ts
Original file line number Diff line number Diff line change
@@ -259,7 +259,7 @@ export type FiltersObject = {
topics: string[];
};

export type XdrType = "TransactionEnvelope" | "LedgerKey";
export type XdrType = "TransactionEnvelope" | "LedgerKey" | "ScVal";

export type LedgerKeyType =
| "account"