feat(explorer): extend transfers view
This commit is contained in:
parent
532ad3a4b9
commit
496b0b5a90
@ -64,7 +64,9 @@ export const ProposalSummary = ({
|
|||||||
return (
|
return (
|
||||||
<div className="w-auto max-w-lg border-2 border-solid border-vega-light-100 dark:border-vega-dark-200 p-5">
|
<div className="w-auto max-w-lg border-2 border-solid border-vega-light-100 dark:border-vega-dark-200 p-5">
|
||||||
{id && <ProposalStatusIcon id={id} />}
|
{id && <ProposalStatusIcon id={id} />}
|
||||||
{rationale?.title && <h1 className="text-xl pb-1">{rationale.title}</h1>}
|
{rationale?.title && (
|
||||||
|
<h1 className="text-xl pb-1 break-all">{rationale.title}</h1>
|
||||||
|
)}
|
||||||
{rationale?.description && (
|
{rationale?.description && (
|
||||||
<div className="pt-2 text-sm leading-tight">
|
<div className="pt-2 text-sm leading-tight">
|
||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
query ExplorerTransferVote($id: ID!) {
|
||||||
|
transfer(id: $id) {
|
||||||
|
reference
|
||||||
|
timestamp
|
||||||
|
status
|
||||||
|
reason
|
||||||
|
fromAccountType
|
||||||
|
from
|
||||||
|
to
|
||||||
|
toAccountType
|
||||||
|
asset {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
amount
|
||||||
|
}
|
||||||
|
}
|
59
apps/explorer/src/app/components/txs/details/transfer/__generated__/Transfer.ts
generated
Normal file
59
apps/explorer/src/app/components/txs/details/transfer/__generated__/Transfer.ts
generated
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import * as Types from '@vegaprotocol/types';
|
||||||
|
|
||||||
|
import { gql } from '@apollo/client';
|
||||||
|
import * as Apollo from '@apollo/client';
|
||||||
|
const defaultOptions = {} as const;
|
||||||
|
export type ExplorerTransferVoteQueryVariables = Types.Exact<{
|
||||||
|
id: Types.Scalars['ID'];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type ExplorerTransferVoteQuery = { __typename?: 'Query', transfer?: { __typename?: 'Transfer', reference?: string | null, timestamp: any, status: Types.TransferStatus, reason?: string | null, fromAccountType: Types.AccountType, from: string, to: string, toAccountType: Types.AccountType, amount: string, asset?: { __typename?: 'Asset', id: string } | null } | null };
|
||||||
|
|
||||||
|
|
||||||
|
export const ExplorerTransferVoteDocument = gql`
|
||||||
|
query ExplorerTransferVote($id: ID!) {
|
||||||
|
transfer(id: $id) {
|
||||||
|
reference
|
||||||
|
timestamp
|
||||||
|
status
|
||||||
|
reason
|
||||||
|
fromAccountType
|
||||||
|
from
|
||||||
|
to
|
||||||
|
toAccountType
|
||||||
|
asset {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
amount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useExplorerTransferVoteQuery__
|
||||||
|
*
|
||||||
|
* To run a query within a React component, call `useExplorerTransferVoteQuery` and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useExplorerTransferVoteQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
|
* you can use to render your UI.
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const { data, loading, error } = useExplorerTransferVoteQuery({
|
||||||
|
* variables: {
|
||||||
|
* id: // value for 'id'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useExplorerTransferVoteQuery(baseOptions: Apollo.QueryHookOptions<ExplorerTransferVoteQuery, ExplorerTransferVoteQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useQuery<ExplorerTransferVoteQuery, ExplorerTransferVoteQueryVariables>(ExplorerTransferVoteDocument, options);
|
||||||
|
}
|
||||||
|
export function useExplorerTransferVoteLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerTransferVoteQuery, ExplorerTransferVoteQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useLazyQuery<ExplorerTransferVoteQuery, ExplorerTransferVoteQueryVariables>(ExplorerTransferVoteDocument, options);
|
||||||
|
}
|
||||||
|
export type ExplorerTransferVoteQueryHookResult = ReturnType<typeof useExplorerTransferVoteQuery>;
|
||||||
|
export type ExplorerTransferVoteLazyQueryHookResult = ReturnType<typeof useExplorerTransferVoteLazyQuery>;
|
||||||
|
export type ExplorerTransferVoteQueryResult = Apollo.QueryResult<ExplorerTransferVoteQuery, ExplorerTransferVoteQueryVariables>;
|
@ -111,7 +111,7 @@ export function TransferParticipants({
|
|||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 16 9"
|
viewBox="0 0 16 9"
|
||||||
className="fill-vega-light-100 dark:fill-black"
|
className="fill-white dark:fill-black"
|
||||||
>
|
>
|
||||||
<path d="M0,0L8,9l8,-9Z" />
|
<path d="M0,0L8,9l8,-9Z" />
|
||||||
</svg>
|
</svg>
|
||||||
@ -120,7 +120,7 @@ export function TransferParticipants({
|
|||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 16 9"
|
viewBox="0 0 16 9"
|
||||||
className="fill-vega-light-100 dark:fill-vega-dark-200"
|
className="fill-vega-light-200 dark:fill-vega-dark-200"
|
||||||
>
|
>
|
||||||
<path d="M0,0L8,9l8,-9Z" />
|
<path d="M0,0L8,9l8,-9Z" />
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -4,6 +4,7 @@ import { headerClasses, wrapperClasses } from '../transfer-details';
|
|||||||
import type { components } from '../../../../../../types/explorer';
|
import type { components } from '../../../../../../types/explorer';
|
||||||
import type { Recurring } from '../transfer-details';
|
import type { Recurring } from '../transfer-details';
|
||||||
import { DispatchMetricLabels } from '@vegaprotocol/types';
|
import { DispatchMetricLabels } from '@vegaprotocol/types';
|
||||||
|
import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
export type Metric = components['schemas']['vegaDispatchMetric'];
|
export type Metric = components['schemas']['vegaDispatchMetric'];
|
||||||
export type Strategy = components['schemas']['vegaDispatchStrategy'];
|
export type Strategy = components['schemas']['vegaDispatchStrategy'];
|
||||||
@ -13,6 +14,15 @@ const metricLabels: Record<Metric, string> = {
|
|||||||
...DispatchMetricLabels,
|
...DispatchMetricLabels,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Maps the two (non-null) values of entityScope to the icon that represents it
|
||||||
|
const entityScopeIcons: Record<
|
||||||
|
string,
|
||||||
|
typeof VegaIconNames[keyof typeof VegaIconNames]
|
||||||
|
> = {
|
||||||
|
ENTITY_SCOPE_INDIVIDUALS: VegaIconNames.MAN,
|
||||||
|
ENTITY_SCOPE_TEAMS: VegaIconNames.TEAM,
|
||||||
|
};
|
||||||
|
|
||||||
interface TransferRewardsProps {
|
interface TransferRewardsProps {
|
||||||
recurring: Recurring;
|
recurring: Recurring;
|
||||||
}
|
}
|
||||||
@ -34,7 +44,7 @@ export function TransferRewards({ recurring }: TransferRewardsProps) {
|
|||||||
return (
|
return (
|
||||||
<div className={wrapperClasses}>
|
<div className={wrapperClasses}>
|
||||||
<h2 className={headerClasses}>{t('Reward metrics')}</h2>
|
<h2 className={headerClasses}>{t('Reward metrics')}</h2>
|
||||||
<ul className="relative block rounded-lg py-6 text-center p-6">
|
<ul className="relative block rounded-lg py-6 text-left p-6">
|
||||||
{recurring.dispatchStrategy.assetForMetric ? (
|
{recurring.dispatchStrategy.assetForMetric ? (
|
||||||
<li>
|
<li>
|
||||||
<strong>{t('Asset')}</strong>:{' '}
|
<strong>{t('Asset')}</strong>:{' '}
|
||||||
@ -44,6 +54,27 @@ export function TransferRewards({ recurring }: TransferRewardsProps) {
|
|||||||
<li>
|
<li>
|
||||||
<strong>{t('Metric')}</strong>: {metricLabels[metric]}
|
<strong>{t('Metric')}</strong>: {metricLabels[metric]}
|
||||||
</li>
|
</li>
|
||||||
|
{recurring.dispatchStrategy.entityScope &&
|
||||||
|
entityScopeIcons[recurring.dispatchStrategy.entityScope] ? (
|
||||||
|
<li>
|
||||||
|
<strong>{t('Scope')}</strong>:{' '}
|
||||||
|
<VegaIcon
|
||||||
|
name={entityScopeIcons[recurring.dispatchStrategy.entityScope]}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{recurring.dispatchStrategy.individualScope}
|
||||||
|
{recurring.dispatchStrategy.teamScope}
|
||||||
|
|
||||||
|
{recurring.dispatchStrategy.lockPeriod &&
|
||||||
|
recurring.dispatchStrategy.lockPeriod !== '0' ? (
|
||||||
|
<li>
|
||||||
|
<strong>{t('Lock')}</strong>:{' '}
|
||||||
|
{recurring.dispatchStrategy.lockPeriod}
|
||||||
|
</li>
|
||||||
|
) : null}
|
||||||
|
|
||||||
{recurring.dispatchStrategy.markets &&
|
{recurring.dispatchStrategy.markets &&
|
||||||
recurring.dispatchStrategy.markets.length > 0 ? (
|
recurring.dispatchStrategy.markets.length > 0 ? (
|
||||||
<li>
|
<li>
|
||||||
@ -57,9 +88,30 @@ export function TransferRewards({ recurring }: TransferRewardsProps) {
|
|||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
) : null}
|
) : null}
|
||||||
<li>
|
|
||||||
<strong>{t('Factor')}</strong>: {recurring.factor}
|
{recurring.dispatchStrategy.stakingRequirement &&
|
||||||
</li>
|
recurring.dispatchStrategy.stakingRequirement !== '0' ? (
|
||||||
|
<li>
|
||||||
|
<strong>{t('Staking requirement')}</strong>:{' '}
|
||||||
|
{recurring.dispatchStrategy.stakingRequirement}
|
||||||
|
</li>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{recurring.dispatchStrategy.windowLength &&
|
||||||
|
recurring.dispatchStrategy.windowLength !== '0' ? (
|
||||||
|
<li>
|
||||||
|
<strong>{t('Window length')}</strong>:{' '}
|
||||||
|
{recurring.dispatchStrategy.windowLength}
|
||||||
|
</li>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{recurring.dispatchStrategy.rankTable &&
|
||||||
|
recurring.dispatchStrategy.rankTable.length > 0 ? (
|
||||||
|
<li>
|
||||||
|
<strong>{t('Ranks')}</strong>:{' '}
|
||||||
|
{recurring.dispatchStrategy.rankTable.toString()}
|
||||||
|
</li>
|
||||||
|
) : null}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import { headerClasses, wrapperClasses } from '../transfer-details';
|
||||||
|
import { Icon, Loader } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import type { ApolloError } from '@apollo/client';
|
||||||
|
|
||||||
|
interface TransferStatusProps {
|
||||||
|
status: string;
|
||||||
|
error: ApolloError | undefined;
|
||||||
|
loading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renderer for a transfer. These can vary quite
|
||||||
|
* widely, essentially every field can be null.
|
||||||
|
*
|
||||||
|
* @param transfer A recurring transfer object
|
||||||
|
*/
|
||||||
|
export function TransferStatusView({ status, loading }: TransferStatusProps) {
|
||||||
|
if (!status) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={wrapperClasses}>
|
||||||
|
<h2 className={headerClasses}>{t('Status')}</h2>
|
||||||
|
<div className="relative block rounded-lg py-6 text-center p-6">
|
||||||
|
{loading ? (
|
||||||
|
<Loader />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<p className="leading-10 my-2">
|
||||||
|
<Icon name="tick" className="text-green-500" />
|
||||||
|
</p>
|
||||||
|
<p className="leading-10 my-2">{status}</p>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -2,6 +2,9 @@ import type { components } from '../../../../../types/explorer';
|
|||||||
import { TransferRepeat } from './blocks/transfer-repeat';
|
import { TransferRepeat } from './blocks/transfer-repeat';
|
||||||
import { TransferRewards } from './blocks/transfer-rewards';
|
import { TransferRewards } from './blocks/transfer-rewards';
|
||||||
import { TransferParticipants } from './blocks/transfer-participants';
|
import { TransferParticipants } from './blocks/transfer-participants';
|
||||||
|
import { useExplorerTransferVoteQuery } from './__generated__/Transfer';
|
||||||
|
import { TransferStatusView } from './blocks/transfer-status';
|
||||||
|
import { TransferStatus } from '@vegaprotocol/types';
|
||||||
|
|
||||||
export type Recurring = components['schemas']['commandsv1RecurringTransfer'];
|
export type Recurring = components['schemas']['commandsv1RecurringTransfer'];
|
||||||
export type Metric = components['schemas']['vegaDispatchMetric'];
|
export type Metric = components['schemas']['vegaDispatchMetric'];
|
||||||
@ -16,6 +19,9 @@ export type Transfer = components['schemas']['commandsv1Transfer'];
|
|||||||
interface TransferDetailsProps {
|
interface TransferDetailsProps {
|
||||||
transfer: Transfer;
|
transfer: Transfer;
|
||||||
from: string;
|
from: string;
|
||||||
|
id: string;
|
||||||
|
// If set, all blocks except the status one are hidden
|
||||||
|
statusOnly?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,15 +30,37 @@ interface TransferDetailsProps {
|
|||||||
*
|
*
|
||||||
* @param transfer A recurring transfer object
|
* @param transfer A recurring transfer object
|
||||||
*/
|
*/
|
||||||
export function TransferDetails({ transfer, from }: TransferDetailsProps) {
|
export function TransferDetails({
|
||||||
|
transfer,
|
||||||
|
from,
|
||||||
|
id,
|
||||||
|
statusOnly = false,
|
||||||
|
}: TransferDetailsProps) {
|
||||||
const recurring = transfer.recurring;
|
const recurring = transfer.recurring;
|
||||||
|
|
||||||
|
// Currently all this is passed in to TransferStatus, but the extra details
|
||||||
|
// may be useful in the future.
|
||||||
|
const { data, error, loading } = useExplorerTransferVoteQuery({
|
||||||
|
variables: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
const status = error
|
||||||
|
? TransferStatus.STATUS_REJECTED
|
||||||
|
: data?.transfer?.status;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-5 flex-wrap">
|
<div className="flex gap-5 flex-wrap">
|
||||||
<TransferParticipants from={from} transfer={transfer} />
|
{statusOnly ? null : (
|
||||||
{recurring ? <TransferRepeat recurring={transfer.recurring} /> : null}
|
<>
|
||||||
{recurring && recurring.dispatchStrategy ? (
|
<TransferParticipants from={from} transfer={transfer} />
|
||||||
<TransferRewards recurring={transfer.recurring} />
|
{recurring ? <TransferRepeat recurring={transfer.recurring} /> : null}
|
||||||
|
{recurring && recurring.dispatchStrategy ? (
|
||||||
|
<TransferRewards recurring={transfer.recurring} />
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{status ? (
|
||||||
|
<TransferStatusView status={status} error={error} loading={loading} />
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -12,6 +12,8 @@ import { ProposalSignatureBundleNewAsset } from './proposal/signature-bundle-new
|
|||||||
import { ProposalSignatureBundleUpdateAsset } from './proposal/signature-bundle-update';
|
import { ProposalSignatureBundleUpdateAsset } from './proposal/signature-bundle-update';
|
||||||
import { MarketLink } from '../../links';
|
import { MarketLink } from '../../links';
|
||||||
import { formatNumber } from '@vegaprotocol/utils';
|
import { formatNumber } from '@vegaprotocol/utils';
|
||||||
|
import { TransferDetails } from './transfer/transfer-details';
|
||||||
|
import { proposalToTransfer } from '../lib/proposal-to-transfer';
|
||||||
|
|
||||||
export type Proposal = components['schemas']['v1ProposalSubmission'];
|
export type Proposal = components['schemas']['v1ProposalSubmission'];
|
||||||
export type ProposalTerms = components['schemas']['vegaProposalTerms'];
|
export type ProposalTerms = components['schemas']['vegaProposalTerms'];
|
||||||
@ -104,6 +106,12 @@ export const TxProposal = ({ txData, pubKey, blockData }: TxProposalProps) => {
|
|||||||
? ProposalSignatureBundleNewAsset
|
? ProposalSignatureBundleNewAsset
|
||||||
: ProposalSignatureBundleUpdateAsset;
|
: ProposalSignatureBundleUpdateAsset;
|
||||||
|
|
||||||
|
let transfer, from;
|
||||||
|
if (proposal.terms?.newTransfer?.changes) {
|
||||||
|
transfer = proposalToTransfer(proposal.terms?.newTransfer.changes);
|
||||||
|
from = proposal.terms.newTransfer.changes.source;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableWithTbody className="mb-8" allowWrap={true}>
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
@ -149,14 +157,27 @@ export const TxProposal = ({ txData, pubKey, blockData }: TxProposalProps) => {
|
|||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
</TableWithTbody>
|
</TableWithTbody>
|
||||||
|
|
||||||
<ProposalSummary
|
<ProposalSummary
|
||||||
id={deterministicId}
|
id={deterministicId}
|
||||||
rationale={proposal.rationale}
|
rationale={proposal.rationale}
|
||||||
terms={proposal?.terms}
|
terms={proposal?.terms}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{proposalRequiresSignatureBundle(proposal) && (
|
{proposalRequiresSignatureBundle(proposal) && (
|
||||||
<SignatureBundleComponent id={deterministicId} tx={tx} />
|
<SignatureBundleComponent id={deterministicId} tx={tx} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{transfer && (
|
||||||
|
<div className="mt-8">
|
||||||
|
<TransferDetails
|
||||||
|
statusOnly={false}
|
||||||
|
transfer={transfer}
|
||||||
|
from={from || ''}
|
||||||
|
id={deterministicId}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -60,7 +60,7 @@ export const TxDetailsTransfer = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const from = txData.submitter;
|
const from = txData.submitter;
|
||||||
|
const id = txSignatureToDeterministicId(txData.signature.value);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableWithTbody className="mb-8" allowWrap={true}>
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
@ -70,9 +70,7 @@ export const TxDetailsTransfer = ({
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered" data-testid="id">
|
<TableRow modifier="bordered" data-testid="id">
|
||||||
<TableCell {...sharedHeaderProps}>{t('Transfer ID')}</TableCell>
|
<TableCell {...sharedHeaderProps}>{t('Transfer ID')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>{id}</TableCell>
|
||||||
{txSignatureToDeterministicId(txData.signature.value)}
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TxDetailsShared
|
<TxDetailsShared
|
||||||
txData={txData}
|
txData={txData}
|
||||||
@ -105,7 +103,7 @@ export const TxDetailsTransfer = ({
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
) : null}
|
) : null}
|
||||||
</TableWithTbody>
|
</TableWithTbody>
|
||||||
<TransferDetails from={from} transfer={transfer} />
|
<TransferDetails from={from} transfer={transfer} id={id} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
import type { components } from '../../../../types/explorer';
|
||||||
|
|
||||||
|
type TransferProposal = components['schemas']['vegaNewTransferConfiguration'];
|
||||||
|
type ActualTransfer = components['schemas']['commandsv1Transfer'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a governance proposal for a transfer in to a transfer command that the
|
||||||
|
* TransferDetails component can then render. The types are very similar, but do not
|
||||||
|
* map precisely to each other due to some missing fields and some different field
|
||||||
|
* names.
|
||||||
|
*
|
||||||
|
* @param proposal Governance proposal for a transfer
|
||||||
|
* @returns transfer a Transfer object as if it had been submitted
|
||||||
|
*/
|
||||||
|
export function proposalToTransfer(proposal: TransferProposal): ActualTransfer {
|
||||||
|
return {
|
||||||
|
amount: proposal.amount,
|
||||||
|
asset: proposal.asset,
|
||||||
|
// On a transfer, 'from' is determined by the submitter, so there is no 'from' field
|
||||||
|
// fromAccountType does exist and is just named differently on the proposal
|
||||||
|
fromAccountType: proposal.sourceType,
|
||||||
|
oneOff: proposal.oneOff,
|
||||||
|
recurring: proposal.recurring,
|
||||||
|
// There is no reference applied on governance initiated transfers
|
||||||
|
reference: '',
|
||||||
|
to: proposal.destination,
|
||||||
|
toAccountType: proposal.destinationType,
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user