Skip to content

Commit

Permalink
update generate flow
Browse files Browse the repository at this point in the history
  • Loading branch information
daoauth committed Dec 24, 2024
1 parent 9d7201b commit 7fedec6
Show file tree
Hide file tree
Showing 6 changed files with 275 additions and 15 deletions.
7 changes: 4 additions & 3 deletions packages/ptb-builder/src/components/Code.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Resizable } from 're-resizable';
import 'prismjs/themes/prism-tomorrow.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers';
import { enqueueToast } from '../provider';
import { enqueueToast, useStateContext } from '../provider';
import { PTBEdge, PTBNode } from '../ptbFlow/nodes';
import { generateCode, generateTxb } from '../utilities/ptb';

Expand All @@ -22,6 +22,7 @@ export const Code = ({
}) => {
const language = 'javascript';

const { wallet } = useStateContext();
const [code, setCode] = useState<string>('');
const [isVisible, setIsVisible] = useState<boolean>(true);
const [isExcute, setIsExcute] = useState<boolean>(false);
Expand All @@ -30,8 +31,8 @@ export const Code = ({
if (excuteTx && !isExcute) {
try {
setIsExcute(true);
// const transaction = await generateTxb(nodes, edges);
// await excuteTx(transaction);
const transaction = await generateTxb(nodes, edges, wallet);
await excuteTx(transaction);
} catch (error) {
enqueueToast(`${error}`, { variant: 'error' });
} finally {
Expand Down
2 changes: 1 addition & 1 deletion packages/ptb-builder/src/ptbFlow/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ export const PTBFlow = ({
}
// eslint-disable-next-line no-restricted-syntax
debounceRef.current = null;
}, 30);
}, 100);
}
}, [disableUpdate, edges, network, nodes, ptbJson, setState, update]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const MakeMoveVec = ({ id, data }: PTBNodeProp) => {
paramLength: (number | undefined)[],
) => {
setType(type);
data.makeMoveVector = type;
data.getIoLength = () => paramLength;
}}
/>
Expand Down
4 changes: 0 additions & 4 deletions packages/ptb-builder/src/utilities/ptb/generateCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,14 @@ const genereateCommand = (
const typeparams = inputs[2]
?.map((v) => connvert(v, dictionary))
.join(', ');

const moveCallArgs = {
target,
...(params && { arguments: `[${params}]` }),
...(typeparams && { typeArguments: `[${typeparams}]` }),
};

const formattedArgs = Object.entries(moveCallArgs)
.map(([key, value]) => `\t${key}: ${value}`)
.join(',\n');

return `tx.moveCall({\n${formattedArgs},\n})`;
}
case PTBNodeType.Publish:
Expand Down Expand Up @@ -134,7 +131,6 @@ export const generateCode = (nodes: PTBNode[], edges: PTBEdge[]): string => {
'',
);
});

commands.forEach(({ node, inputs, results }) => {
if (results) {
const name = `cmd_${cmdIndex++}`;
Expand Down
8 changes: 2 additions & 6 deletions packages/ptb-builder/src/utilities/ptb/generateFlow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ const preprocess = (
outputs: new Array(ioLength[1] || amounts.length).fill(undefined),
};
}

case PTBNodeType.TransferObjects: {
const address = getSourceHandleID('address', 'address');
const objects =
Expand Down Expand Up @@ -165,7 +164,6 @@ const preprocess = (
node.data.moveCall.function,
]
: [undefined];

const typeParams = forMoveCall('type', ioLength[0] || 0);
const params = forMoveCall('input', ioLength[1] || 0);
return {
Expand All @@ -174,12 +172,10 @@ const preprocess = (
};
}
case PTBNodeType.Publish:
break;

return { inputs: [], outputs: [undefined] };
default:
break;
return { inputs: [] };
}
return { inputs: [], outputs: [] };
};

export const generateFlow = (
Expand Down
268 changes: 267 additions & 1 deletion packages/ptb-builder/src/utilities/ptb/generateTxb.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,269 @@
import {
Transaction,
TransactionArgument,
TransactionObjectArgument,
TransactionResult,
} from '@mysten/sui/transactions';

import { generateFlow } from './generateFlow';
import { PTBEdge, PTBNode, PTBNodeType } from '../../ptbFlow/nodes';

type DictionaryItem =
| number
| string
| TransactionObjectArgument
| TransactionResult;

interface NestedResult {
$kind: 'NestedResult';
NestedResult: [number, number];
}

const connvert = (
id: string | undefined,
dictionary: Record<string, undefined | DictionaryItem | DictionaryItem[]>,
): undefined | DictionaryItem | DictionaryItem[] => {
if (id === undefined) {
return undefined;
}
const match = id.match(/\[(\d+)\]$/);
if (match) {
const index = match[1];
const data = dictionary[id.replace(`[${index}]`, '')];
if (data && Array.isArray(data)) {
return data[parseInt(index, 10)];
}
return undefined;
}
return dictionary[id];
};

const genereateCommand = (
node: PTBNode,
inputs: (string | undefined)[][],
dictionary: Record<string, undefined | DictionaryItem | DictionaryItem[]>,
tx: Transaction,
results?: (string | undefined)[],
): {
tx: Transaction;
nestedResults?: TransactionResult | NestedResult[];
} => {
try {
switch (node.type) {
case PTBNodeType.SplitCoins: {
const coin = inputs[0][0];
const amounts = inputs[1].map((v) => connvert(v, dictionary));
if (coin && dictionary[coin]) {
const result = tx.splitCoins(
dictionary[coin] as TransactionObjectArgument,
amounts as number[],
);
return {
tx,
nestedResults: (amounts as any[]).map(
(_, i) => result[i] as NestedResult,
),
};
}
throw new Error(`Invalid parameters for ${node.type}`);
}
case PTBNodeType.MergeCoins: {
const destination = inputs[0][0];
const sources = inputs[1].map((v) => connvert(v, dictionary));
if (destination && dictionary[destination]) {
tx.mergeCoins(
dictionary[destination] as TransactionObjectArgument,
sources as TransactionObjectArgument[],
);
return { tx };
}
throw new Error(`Invalid parameters for ${node.type}`);
}
case PTBNodeType.TransferObjects: {
const objects = inputs[1].map((v) => connvert(v, dictionary));
const address = inputs[0][0];
if (address && dictionary[address]) {
tx.transferObjects(
objects as TransactionObjectArgument[],
dictionary[address] as TransactionObjectArgument,
);
return { tx };
}
throw new Error(`Invalid parameters for ${node.type}`);
}
case PTBNodeType.MakeMoveVec: {
const type = inputs[0][0];
const elements = inputs[1].map((v) => connvert(v, dictionary));
if (type) {
const result = tx.makeMoveVec({
type: type,
elements: elements.map((v) => {
switch (type) {
case 'address':
return tx.pure.address(v as string);
case 'string':
return tx.pure.string(v as string);
case 'u8':
return tx.pure.u8(v as number);
case 'u16':
return tx.pure.u16(v as number);
case 'u32':
return tx.pure.u32(v as number);
case 'u64':
return tx.pure.u64(v as number);
case 'u128':
return tx.pure.u128(v as number);
case 'u256':
return tx.pure.u256(v as number);
case 'object':
return tx.object(`${v}`);
case 'bool':
return tx.pure.bool(v === 'true');
default:
return `${v}`;
}
}),
});
return { tx, nestedResults: result };
}
throw new Error(`Invalid parameters for ${node.type}`);
}
case PTBNodeType.MoveCall: {
const target =
inputs[0][0] !== undefined ? `${inputs[0].join('::')}` : undefined;
const argument =
inputs[1] && inputs[1].length > 0
? inputs[1].map(
(v) => connvert(v, dictionary) as TransactionArgument,
)
: undefined;
const typeArguments =
inputs[2] && inputs[2].length > 0
? inputs[2].map((v) => connvert(v, dictionary) as string)
: undefined;
if (target) {
const result = tx.moveCall({
target,
...(argument && { arguments: argument }),
...(typeArguments && { typeArguments: typeArguments }),
});
return {
tx,
nestedResults:
results &&
(results as any[]).map((_, i) => result[i] as NestedResult),
};
}
throw new Error(`Invalid parameters for ${node.type}`);
}
case PTBNodeType.Publish:
default:
throw new Error(`Invalid command type: ${node.type}`);
}
} catch (error) {
throw new Error(`Failed to generate command: ${error}`);
}
};

export const generateTxb = async (
nodes: PTBNode[],
edges: PTBEdge[],
wallet?: string,
): Promise<Transaction> => {
try {
const { inputs, commands } = generateFlow(nodes, edges);
let tx = new Transaction();

const dictionary: Record<
string,
undefined | DictionaryItem | DictionaryItem[]
> = {};
Object.keys(inputs).forEach((key) => {
const { value } = inputs[key].data;
switch (inputs[key].type) {
case PTBNodeType.Address:
dictionary[key] = tx.pure.address(value as string);
break;
case PTBNodeType.AddressWallet:
if (wallet) {
dictionary[key] = tx.pure.address(wallet);
} else {
throw new Error('Wallet is required');
}
break;
case PTBNodeType.AddressArray:
dictionary[key] = (value as string[]).map((v) =>
tx.pure.address(value as string),
);
break;
case PTBNodeType.Bool:
dictionary[key] = tx.pure.bool(value === 'true');
break;
case PTBNodeType.BoolArray:
dictionary[key] = (value as string[]).map((v) =>
tx.pure.bool(value === 'true'),
);
break;
case PTBNodeType.String:
dictionary[key] = value as string;
break;
case PTBNodeType.Number:
dictionary[key] = value as number;
break;
case PTBNodeType.NumberArray:
dictionary[key] = (value as number[]).map((v) => v);
break;
case PTBNodeType.Object:
dictionary[key] = tx.object(value as string);
break;
case PTBNodeType.ObjectArray:
dictionary[key] = (value as string[]).map((v) =>
tx.object(value as string),
);
break;
case PTBNodeType.ObjectClock:
dictionary[key] = tx.object.clock();
break;
case PTBNodeType.ObjectDenyList:
dictionary[key] = tx.object.denyList();
break;
case PTBNodeType.ObjectGas:
dictionary[key] = tx.gas;
break;
case PTBNodeType.ObjectRandom:
dictionary[key] = tx.object.random();
break;
case PTBNodeType.ObjectSystem:
dictionary[key] = tx.object.system();
break;
case PTBNodeType.ObjectOption:
const temp = inputs[key].data.value;
if (temp && Array.isArray(temp)) {
dictionary[key] = tx.object.option({
type: temp[0] as string,
value: temp[1] as string,
})(tx);
}
break;
default:
break;
}
});

commands.forEach(({ node, inputs, results }) => {
const { tx: tx2, nestedResults } = genereateCommand(
node,
inputs,
dictionary,
tx,
results,
);
tx = tx2;
dictionary[node.id] = nestedResults;
});

export const generateTxb = generateFlow;
return tx;
} catch (error) {
throw new Error(`${error}`);
}
};

0 comments on commit 7fedec6

Please sign in to comment.