Wallets

API: Internal/Beta

Wallets hold allocations which grant access to a provider’s resources.

Rationale

Wallets are the core abstraction used in the accounting system of UCloud. This feature builds on top of various other features of UCloud. Here is a quick recap:

  • The users of UCloud are members of Workspaces and Projects. These form the foundation of all collaboration in UCloud.

  • UCloud is an orchestrator of Resources. UCloud delegates the responsibility of hosting Resources to Providers.

  • Providers define which services they support using Products.

  • All Products belong in a ProductCategory. The category contains similar Products. Under normal circumstances, all products in a category run on the same system.

  • Products define a payment model. The model supports quotas (DIFFERENTIAL_QUOTA), one-time payments and periodic payments (ABSOLUTE). All absolute payment models support paying in a product-specific unit or in DKK.

  • All Products in a category share the exact same payment model

Allocators grant access to Resources via WalletAllocations. In a simplified view, an allocation is:

  • An initial balance, specified in the “unit of allocation” which the Product specifies. For example: 1000 DKK or 500 Core Hours.

  • Start date and optional end date.

  • An optional parent allocation.

  • A current balance, the balance remaining for this allocation and all descendants.

  • A local balance, the balance remaining if it had no descendants

UCloud combines allocations of the same category into a Wallet Every Wallet has exactly one owner, a workspace. Wallets create a natural hierarchical structure. Below we show an example of this:

Figure: Allocations create a natural allocation hierarchy.


📝NOTE: The wallet and accounting systems are currently considered internal due to some limitations in the API. We aim to keep the provider API (the control interfaces) stable but the accounting system itself will remain at an internal level until we have resolved the issues at an API level. We plan on making this API stable in the long-term.


Table of Contents

1. Remote Procedure Calls
Name Description
browse Browses the catalog of accessible Wallets
browseSubAllocations Browses the catalog of sub-allocations
retrieveProviderSummary Retrieves a provider summary of relevant wallets
retrieveRecipient Retrieves information about a potential WalletAllocation recipient
searchSubAllocations Searches the catalog of sub-allocations
push Pushes a Wallet to the catalog
register Registers an allocation created outside of UCloud
2. Data Models
Name Description
Wallet Wallets hold allocations which grant access to a provider's resources.
WalletAllocation An allocation grants access to resources
AllocationSelectorPolicy A policy for how to select a WalletAllocation in a single Wallet
ProviderWalletSummary No description
SubAllocation A parent allocator's view of a `WalletAllocation`
WalletOwner No description
WalletOwner.Project No description
WalletOwner.User No description
PushWalletChangeRequestItem No description
RegisterWalletRequestItem No description
WalletBrowseRequest The base type for requesting paginated content.
WalletsBrowseSubAllocationsRequest No description
WalletsRetrieveProviderSummaryRequest The base type for requesting paginated content.
WalletsRetrieveRecipientRequest No description
WalletsSearchSubAllocationsRequest No description
WalletsRetrieveRecipientResponse No description

Remote Procedure Calls

browse

API: Internal/Beta Auth: Users

Browses the catalog of accessible Wallets

Request Response Error
WalletBrowseRequest PageV2<Wallet> CommonErrorMessage

browseSubAllocations

API: Internal/Beta Auth: Users

Browses the catalog of sub-allocations

Request Response Error
WalletsBrowseSubAllocationsRequest PageV2<SubAllocation> CommonErrorMessage

This endpoint will find all WalletAllocations which are direct children of one of your accessible WalletAllocations.

retrieveProviderSummary

API: Internal/Beta Auth: Provider

Retrieves a provider summary of relevant wallets

Request Response Error
WalletsRetrieveProviderSummaryRequest PageV2<ProviderWalletSummary> CommonErrorMessage

This endpoint is only usable by providers. The endpoint will return a stable sorted summary of all allocations that a provider currently has.

retrieveRecipient

API: Internal/Beta Auth: Users

Retrieves information about a potential WalletAllocation recipient

Request Response Error
WalletsRetrieveRecipientRequest WalletsRetrieveRecipientResponse CommonErrorMessage

You can use this endpoint to find information about a Workspace. This is useful when creating a sub-allocation.

searchSubAllocations

API: Internal/Beta Auth: Users

Searches the catalog of sub-allocations

Request Response Error
WalletsSearchSubAllocationsRequest PageV2<SubAllocation> CommonErrorMessage

This endpoint will find all WalletAllocations which are direct children of one of your accessible WalletAllocations.

push

API: Experimental/Beta Auth: Provider

Pushes a Wallet to the catalog

Request Response Error
BulkRequest<PushWalletChangeRequestItem> Unit CommonErrorMessage

Be careful with using this endpoint as it might go away in a future release.

register

API: Experimental/Beta Auth: Provider

Registers an allocation created outside of UCloud

Request Response Error
BulkRequest<RegisterWalletRequestItem> Unit CommonErrorMessage

Be careful with using this endpoint as it might go away in a future release.

Data Models

Wallet

API: Internal/Beta

Wallets hold allocations which grant access to a provider’s resources.

data class Wallet(
    val owner: WalletOwner,
    val paysFor: ProductCategoryId,
    val allocations: List<WalletAllocation>,
    val chargePolicy: AllocationSelectorPolicy,
    val productType: ProductType?,
    val chargeType: ChargeType?,
    val unit: ProductPriceUnit?,
)

You can find more information about WalletAllocations here.

Properties
owner: WalletOwner
paysFor: ProductCategoryId
allocations: List<WalletAllocation>
chargePolicy: AllocationSelectorPolicy
productType: ProductType?
chargeType: ChargeType?
unit: ProductPriceUnit?

WalletAllocation

API: Internal/Beta

An allocation grants access to resources

data class WalletAllocation(
    val id: String,
    val allocationPath: List<String>,
    val balance: Long,
    val initialBalance: Long,
    val localBalance: Long,
    val startDate: Long,
    val endDate: Long?,
    val grantedIn: Long?,
    val canAllocate: Boolean?,
    val allowSubAllocationsToAllocate: Boolean?,
)

You can find more information about WalletAllocations here.

Properties
id: String A unique ID of this allocation
allocationPath: List<String> A path, starting from the top, through the allocations that will be charged, when a charge is made

Note that this allocation path will always include, as its last element, this allocation.

balance: Long The current balance of this wallet allocation's subtree
initialBalance: Long The initial balance which was granted to this allocation
localBalance: Long The current balance of this wallet allocation
startDate: Long Timestamp for when this allocation becomes valid
endDate: Long? Timestamp for when this allocation becomes invalid, null indicates that this allocation does not expire automatically
grantedIn: Long? ID reference to which grant application this allocation was granted in
canAllocate: Boolean? A property which indicates if this allocation can be used to create sub-allocations
allowSubAllocationsToAllocate: Boolean? A property which indicates that new sub-allocations of this allocation by default should have canAllocate = true

AllocationSelectorPolicy

API: Internal/Beta

A policy for how to select a WalletAllocation in a single Wallet

enum class AllocationSelectorPolicy {
    EXPIRE_FIRST,
}
Properties
EXPIRE_FIRST Use the WalletAllocation which is closest to expiration

ProviderWalletSummary

API: Internal/Beta

data class ProviderWalletSummary(
    val id: String,
    val owner: WalletOwner,
    val categoryId: ProductCategoryId,
    val productType: ProductType,
    val chargeType: ChargeType,
    val unitOfPrice: ProductPriceUnit,
    val maxUsableBalance: Long,
    val maxPromisedBalance: Long,
    val notBefore: Long,
    val notAfter: Long?,
)
Properties
id: String
owner: WalletOwner
categoryId: ProductCategoryId
productType: ProductType
chargeType: ChargeType
unitOfPrice: ProductPriceUnit
maxUsableBalance: Long Maximum balance usable until a charge would fail

This balance is calculated when the data is requested and thus can immediately become invalid due to changes in the tree.

maxPromisedBalance: Long Maximum balance usable as promised by a top-level grant giver

This balance is calculated when the data is requested and thus can immediately become invalid due to changes in the tree.

notBefore: Long The earliest timestamp which allows for the balance to be consumed
notAfter: Long? The earliest timestamp at which the reported balance is no longer fully usable

SubAllocation

API: Experimental/Alpha

A parent allocator’s view of a WalletAllocation

data class SubAllocation(
    val id: String,
    val path: String,
    val startDate: Long,
    val endDate: Long?,
    val productCategoryId: ProductCategoryId,
    val productType: ProductType,
    val chargeType: ChargeType,
    val unit: ProductPriceUnit,
    val workspaceId: String,
    val workspaceTitle: String,
    val workspaceIsProject: Boolean,
    val projectPI: String?,
    val remaining: Long,
    val initialBalance: Long,
)
Properties
id: String
path: String
startDate: Long
endDate: Long?
productCategoryId: ProductCategoryId
productType: ProductType
chargeType: ChargeType
unit: ProductPriceUnit
workspaceId: String
workspaceTitle: String
workspaceIsProject: Boolean
projectPI: String?
remaining: Long
initialBalance: Long

WalletOwner

API: Internal/Beta

sealed class WalletOwner {
    class Project : WalletOwner()
    class User : WalletOwner()
}

WalletOwner.Project

API: Internal/Beta

data class Project(
    val projectId: String,
    val type: String /* "project" */,
)
Properties
projectId: String
type: String /* "project" */ The type discriminator

API: Stable


WalletOwner.User

API: Internal/Beta

data class User(
    val username: String,
    val type: String /* "user" */,
)
Properties
username: String
type: String /* "user" */ The type discriminator

API: Stable


PushWalletChangeRequestItem

API: Experimental/Beta

data class PushWalletChangeRequestItem(
    val allocationId: String,
    val amount: Long,
)
Properties
allocationId: String
amount: Long

RegisterWalletRequestItem

API: Experimental/Beta

data class RegisterWalletRequestItem(
    val owner: WalletOwner,
    val uniqueAllocationId: String,
    val categoryId: String,
    val balance: Long,
    val providerGeneratedId: String?,
)
Properties
owner: WalletOwner
uniqueAllocationId: String
categoryId: String
balance: Long
providerGeneratedId: String?

WalletBrowseRequest

API: Internal/Beta

The base type for requesting paginated content.

data class WalletBrowseRequest(
    val itemsPerPage: Int?,
    val next: String?,
    val consistency: PaginationRequestV2Consistency?,
    val itemsToSkip: Long?,
    val filterType: ProductType?,
)

Paginated content can be requested with one of the following consistency guarantees, this greatly changes the semantics of the call:

Consistency Description
PREFER Consistency is preferred but not required. An inconsistent snapshot might be returned.
REQUIRE Consistency is required. A request will fail if consistency is no longer guaranteed.

The consistency refers to if collecting all the results via the pagination API are consistent. We consider the results to be consistent if it contains a complete view at some point in time. In practice this means that the results must contain all the items, in the correct order and without duplicates.

If you use the PREFER consistency then you may receive in-complete results that might appear out-of-order and can contain duplicate items. UCloud will still attempt to serve a snapshot which appears mostly consistent. This is helpful for user-interfaces which do not strictly depend on consistency but would still prefer something which is mostly consistent.

The results might become inconsistent if the client either takes too long, or a service instance goes down while fetching the results. UCloud attempts to keep each next token alive for at least one minute before invalidating it. This does not mean that a client must collect all results within a minute but rather that they must fetch the next page within a minute of the last page. If this is not feasible and consistency is not required then PREFER should be used.


📝 NOTE: Services are allowed to ignore extra criteria of the request if the next token is supplied. This is needed in order to provide a consistent view of the results. Clients should provide the same criterion as they paginate through the results.


Properties
itemsPerPage: Int? Requested number of items per page. Supported values: 10, 25, 50, 100, 250.
next: String? A token requesting the next page of items
consistency: PaginationRequestV2Consistency? Controls the consistency guarantees provided by the backend
itemsToSkip: Long? Items to skip ahead
filterType: ProductType?

WalletsBrowseSubAllocationsRequest

API: Internal/Beta

data class WalletsBrowseSubAllocationsRequest(
    val filterType: ProductType?,
    val itemsPerPage: Int?,
    val next: String?,
    val consistency: PaginationRequestV2Consistency?,
    val itemsToSkip: Long?,
)
Properties
filterType: ProductType?
itemsPerPage: Int? Requested number of items per page. Supported values: 10, 25, 50, 100, 250.
next: String? A token requesting the next page of items
consistency: PaginationRequestV2Consistency? Controls the consistency guarantees provided by the backend
itemsToSkip: Long? Items to skip ahead

WalletsRetrieveProviderSummaryRequest

API: Internal/Beta

The base type for requesting paginated content.

data class WalletsRetrieveProviderSummaryRequest(
    val itemsPerPage: Int?,
    val next: String?,
    val consistency: PaginationRequestV2Consistency?,
    val itemsToSkip: Long?,
    val filterOwnerId: String?,
    val filterOwnerIsProject: Boolean?,
    val filterCategory: String?,
)

Paginated content can be requested with one of the following consistency guarantees, this greatly changes the semantics of the call:

Consistency Description
PREFER Consistency is preferred but not required. An inconsistent snapshot might be returned.
REQUIRE Consistency is required. A request will fail if consistency is no longer guaranteed.

The consistency refers to if collecting all the results via the pagination API are consistent. We consider the results to be consistent if it contains a complete view at some point in time. In practice this means that the results must contain all the items, in the correct order and without duplicates.

If you use the PREFER consistency then you may receive in-complete results that might appear out-of-order and can contain duplicate items. UCloud will still attempt to serve a snapshot which appears mostly consistent. This is helpful for user-interfaces which do not strictly depend on consistency but would still prefer something which is mostly consistent.

The results might become inconsistent if the client either takes too long, or a service instance goes down while fetching the results. UCloud attempts to keep each next token alive for at least one minute before invalidating it. This does not mean that a client must collect all results within a minute but rather that they must fetch the next page within a minute of the last page. If this is not feasible and consistency is not required then PREFER should be used.


📝 NOTE: Services are allowed to ignore extra criteria of the request if the next token is supplied. This is needed in order to provide a consistent view of the results. Clients should provide the same criterion as they paginate through the results.


Properties
itemsPerPage: Int? Requested number of items per page. Supported values: 10, 25, 50, 100, 250.
next: String? A token requesting the next page of items
consistency: PaginationRequestV2Consistency? Controls the consistency guarantees provided by the backend
itemsToSkip: Long? Items to skip ahead
filterOwnerId: String?
filterOwnerIsProject: Boolean?
filterCategory: String?

WalletsRetrieveRecipientRequest

API: Internal/Beta

data class WalletsRetrieveRecipientRequest(
    val query: String,
)
Properties
query: String

WalletsSearchSubAllocationsRequest

API: Internal/Beta

data class WalletsSearchSubAllocationsRequest(
    val query: String,
    val filterType: ProductType?,
    val itemsPerPage: Int?,
    val next: String?,
    val consistency: PaginationRequestV2Consistency?,
    val itemsToSkip: Long?,
)
Properties
query: String
filterType: ProductType?
itemsPerPage: Int? Requested number of items per page. Supported values: 10, 25, 50, 100, 250.
next: String? A token requesting the next page of items
consistency: PaginationRequestV2Consistency? Controls the consistency guarantees provided by the backend
itemsToSkip: Long? Items to skip ahead

WalletsRetrieveRecipientResponse

API: Internal/Beta

data class WalletsRetrieveRecipientResponse(
    val id: String,
    val isProject: Boolean,
    val title: String,
    val principalInvestigator: String,
    val numberOfMembers: Int,
)
Properties
id: String
isProject: Boolean
title: String
principalInvestigator: String
numberOfMembers: Int