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

feat(backend): update wallet address additional properties #2769

Merged
merged 12 commits into from
Jun 19, 2024

Conversation

BlairCurrey
Copy link
Contributor

Changes proposed in this pull request

  • Updates walletAddressUpdate mutation so that additionalProperties can be updated

Context

fixes #2740

Checklist

  • Related issues linked using fixes #number
  • Tests added/updated
  • Documentation added
  • Make sure that all checks pass
  • Bruno collection updated

@github-actions github-actions bot added type: tests Testing related pkg: backend Changes in the backend package. pkg: frontend Changes in the frontend package. type: source Changes business logic pkg: mock-ase pkg: mock-account-service-lib labels Jun 7, 2024
Copy link

netlify bot commented Jun 7, 2024

Deploy Preview for brilliant-pasca-3e80ec canceled.

Name Link
🔨 Latest commit c063b93
🔍 Latest deploy log https://app.netlify.com/sites/brilliant-pasca-3e80ec/deploys/6671c348e3f41b00083e4d41

Comment on lines 201 to 212
// Override all existing additional properties if new ones are provided
if (additionalProperties && additionalProperties.length) {
await WalletAddressAdditionalProperty.query(trx)
.where('walletAddressId', id)
.delete()
await WalletAddressAdditionalProperty.query(trx).insert(
additionalProperties.map((prop) => ({
walletAddressId: id,
...prop
}))
)
}
Copy link
Contributor Author

@BlairCurrey BlairCurrey Jun 7, 2024

Choose a reason for hiding this comment

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

Override all existing additional properties if new ones are provided. So it effectively, but not literally, updates existing keys. Doing it this way is simpler - we dont need to add an index for the key, look each one up, check the value, etc. And the result is the same.

.patchAndFetch(update)
.withGraphFetched('asset')
.throwIfNotFound()

// Override all existing additional properties if new ones are provided
if (additionalProperties && additionalProperties.length) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does nothing if additionalProperties is []. Perhaps this is wrong though and an empty array should delete them? Since it's more consistent with how we're otherwise deleting non-existant keys. And because there is currently no way to delete everything.

I did it this way originally because I thought it would be too easy to accidentally delete everything, but now I see that this reasoning would also apply to deleting non-existent keys.

Copy link
Contributor Author

@BlairCurrey BlairCurrey Jun 7, 2024

Choose a reason for hiding this comment

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

I'll let this marinate a bit and welcome feedback, but I think I'm going to change it so that [] overrides the existing (so deleting everything).

I was getting hung-up on feeling like the delete operation in the database is somehow different than updating the publicName, etc. field on wallet address. But its not really from the api consumer perspective - its just overriding the previous value (an array of things) with the new value (a new array of things, empty or otherwise). So it would be quite strange to set additionalProperties to [] and additionalProperties not to be [].

Copy link
Collaborator

Choose a reason for hiding this comment

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

This is a bit of a tricky one. Here is a suggestion:

  • undefined would ignore doing anything to the additional properties
  • [] would delete all the additional properties
  • keys that match existing values, but have their new value is empty, gets deleted
  • new keys with valid values are inserted
  • keys with updated values are updated (non-case-sensitive, not sure if this is already expected to the handled by PSQL behaviour?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree on all counts except I'd rather effectively update existing keys for the reasons stated here: #2769 (comment)

What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree with both of the last two messages 👍 @koekiebox @BlairCurrey

.then((query): UpdateWalletAddressMutationResponse => {
if (query.data) {
return query.data.updateWalletAddress
} else {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok, it is nicer that the additional properties has their own section.

Copy link
Collaborator

@koekiebox koekiebox left a comment

Choose a reason for hiding this comment

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

Couple of items, otherwise it looks good.

{ key: '', value: '', visibleInOpenPayments: false },
{ key: 'key', value: '', visibleInOpenPayments: false },
{ key: '', value: 'val', visibleInOpenPayments: false },
{ key: 'key', value: 'val', visibleInOpenPayments: false },
Copy link
Collaborator

Choose a reason for hiding this comment

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

I just realized that I haven't thought of duplicating key's for additional properties.
Do we want to:

  1. generate an error and reject the create.
  2. Only use the value for the last matching keys.

Copy link
Contributor Author

@BlairCurrey BlairCurrey Jun 12, 2024

Choose a reason for hiding this comment

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

That is an interesting case.

I actually think we should let them do it because it doesn't break nor complicate anything on our end and I dont want to assume there is no valid use-case for duplicate keys. Perhaps they want to group by key or something where only some of the values are private to open payments:

// graphql update wallet address input
const input = {
  additionalProperties: [
    { key: 'myUserArray', value: 'publicUser1', visibleInOpenPayments: 'true' },
    { key: 'myUserArray', value: 'privateUser2', visibleInOpenPayments: 'false' },
    { key: 'myUserArray', value: 'publicUser2', visibleInOpenPayments: 'true' },
    { key: 'nickname', value: 'someNickname', visibleInOpenPayments: 'true' }
  ]
 }

// /GET wallet-address response
const response = {
  additionalProperties: [
    { key: 'myUserArray', value: 'publicUser1', visibleInOpenPayments: 'true' },
    { key: 'myUserArray', value: 'publicUser2', visibleInOpenPayments: 'true' },
    { key: 'nickname', value: 'someNickname', visibleInOpenPayments: 'true' }
  ]
}

// group values by 'myUserArray'
const userArrayValues = response.additionalProperties
  .filter(obj => obj.key === 'myUserArray')
  .map(obj => obj.value);

// users is ["publicUser1", "publicUser2"]

This is a capability we would remove by disallowing duplicate keys. Do they really want to do this? I have no idea - but I think that's their concern and we shouldn't reduce their power to choose to use it this way, or other un-anticipated ways when it doesn't break nor complicate anything on our end.

If duplicate keys from the bad input they provide is a problem on their end they can deduplicate them however they want and re-use the update mutation.

): Promise<WalletAddress | WalletAddressError> {
const trx = await WalletAddress.startTransaction()
try {
const update: UpdateInput = { publicName }
const walletAddress = await WalletAddress.query(deps.knex)
Copy link
Contributor

Choose a reason for hiding this comment

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

not a big deal but should we also use the trx here?

Copy link
Contributor Author

@BlairCurrey BlairCurrey Jun 17, 2024

Choose a reason for hiding this comment

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

I suppose probably so... and more importantly the underlying IncomingPayment.patchin deactivateOpenIncomingPaymentsByWalletAddress (called a few lines below this). Added 8f64e7c

Comment on lines 209 to 212
additionalProperties.map((prop) => ({
walletAddressId: id,
...prop
}))
Copy link
Contributor

Choose a reason for hiding this comment

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

just in case I think we should "clean" the values passed into this. Would probably best to have this "cleaning" made into a fn and also used during create in L150-159.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let me know if you have anything else in mind, but I made a fn that takes the existing check in create (that key/value arent empty) and added a step to trim them to get rid of whitespace. Does that cover what you had in mind?

7c21e2d

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess this suggestion kinda veers into the suggestion to de-duplicate #2769 (comment)

I guess I still prefer to let the caller handle that and not enforce it but I guess if we do this would be the place. Not sure if that's something you had in mind or not.

}
url
publicName
test('Can create a wallet address with additional properties', async (): Promise<void> => {
Copy link
Contributor

Choose a reason for hiding this comment

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

we should check the correct properties were returned in the response

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated f73e66d

.patchAndFetch(update)
.withGraphFetched('asset')
.throwIfNotFound()

// Override all existing additional properties if new ones are provided
if (additionalProperties) {
Copy link
Contributor

Choose a reason for hiding this comment

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

we should add some tests for these

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added: 770c0bd

Copy link
Collaborator

@koekiebox koekiebox left a comment

Choose a reason for hiding this comment

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

LGTM! 🎸

Copy link
Contributor

@mkurapov mkurapov left a comment

Choose a reason for hiding this comment

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

LGTM ✅

@BlairCurrey BlairCurrey merged commit 3bd9669 into main Jun 19, 2024
42 checks passed
@BlairCurrey BlairCurrey deleted the bc/2740/update-wa-additional-properties branch June 19, 2024 02:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg: backend Changes in the backend package. pkg: frontend Changes in the frontend package. pkg: mock-account-service-lib pkg: mock-ase type: source Changes business logic type: tests Testing related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow updateWalletAddress mutation to take in additional properties
3 participants